from django.db import models class InvalidData(Exception): ''' Thrown when the DB contains invalid data, and cannot perform something ''' def __init__(self, what): self.what = what super(InvalidData, self).__init__() def __str__(self): return self.what class Keyword(models.Model): ''' A keyword/search term ''' text = models.CharField(max_length=256) def __str__(self): return self.text class Webpage(models.Model): url = models.URLField() def __str__(self): return self.url class Website(models.Model): ''' A website usually visited ''' name = models.CharField(max_length=256) url = models.URLField() keywords = models.ManyToManyField(Keyword) notable_pages = models.ManyToManyField(Webpage) def __str__(self): return self.name class Place(models.Model): ''' A real-life place ''' name = models.CharField(max_length=256) address = models.CharField(max_length=512) lat = models.FloatField('Latitude', blank=True) lon = models.FloatField('Longitude', blank=True) def __str__(self): return self.name class Event(models.Model): ''' A real-life event (protests, meeting, ...) ''' name = models.CharField(max_length=256) date = models.DateTimeField() place = models.ForeignKey(Place, on_delete=models.CASCADE) def __str__(self): return self.name class BrowserFingerprint(models.Model): ''' A browser fingerprint, containing things like a user agent ''' description = models.CharField(max_length=256) useragent = models.CharField(max_length=256) appname = models.CharField(max_length=256) appversion = models.CharField(max_length=256) platform = models.CharField(max_length=256) vendor = models.CharField(max_length=256) vendorsub = models.CharField(max_length=256) buildID = models.CharField(max_length=256) oscpu = models.CharField(max_length=256) accept_encoding = models.CharField(max_length=256) accept_default = models.CharField(max_length=256) accept_lang = models.CharField(max_length=256) pixeldepth = models.IntegerField() colordepth = models.IntegerField() screens = models.CharField(max_length=256) def __str__(self): return self.description class SearchEngine(models.Model): ''' A search engine, and all the data needed to use it ''' name = models.CharField(max_length=256) url = models.URLField() query_pattern = models.CharField(max_length=256) # This field is the # query pattern. It should contain a `{}`, which, when substituted with a # search term (using `.format()`), must yield a URL that can be resolved to # perform the search def __str__(self): return self.name def search_url(self, search_term): ''' Obtain a url to search `search_term` with this search engine ''' pattern = str(self.query_pattern) if '{}' not in pattern: raise InvalidData("Search engine {}: bad pattern".format(self)) return str(self.query_pattern).format(search_term) class Interest(models.Model): ''' A class of interests ''' name = models.CharField(max_length=256) keywords = models.ManyToManyField(Keyword) places = models.ManyToManyField(Place) websites = models.ManyToManyField(Website) events = models.ManyToManyField(Event) def __str__(self): return self.name class Profile(models.Model): ''' Represents a user profile, containing a few data to make their requests consistent ''' nick = models.CharField(max_length=64, help_text="The user's online identity") first_name = models.CharField(max_length=64) last_name = models.CharField(max_length=64) email = models.EmailField() uses_urls = models.BooleanField( help_text=('Does the user usually go to a given website using its url ' 'or searching it in a search engine?')) interests = models.ManyToManyField(Interest) search_engine = models.ForeignKey(SearchEngine, on_delete=models.CASCADE) browser_fingerprint = models.ForeignKey(BrowserFingerprint, on_delete=models.CASCADE)