Devo aggiungere campi o utilizzare l'ereditarietà in questo caso?

-1

Le case e le auto non hanno quasi nulla in comune, ad esempio "numero di camere" e "cambio". Ma se vivi in un camper, suppongo che abbia senso avere entrambi. Il mio problema è che ho un modello di dati principale chiamato "Annuncio" per gli annunci pubblicitari online e ora stiamo per espandere la sezione sulle automobili. Dovrei quindi estendere l'oggetto Ad con CarAd (Ad) ereditato da Ad o dovrei semplicemente aggiungere campi alla classe di annunci originale?

Mi scuso se il codice sotto è sporco ma è la cosa reale.

class Ad(db.Model): #change to ndb.model
    cities = db.ListProperty(db.Key) #ndb.KeyProperty(repeated=True)
    regions = db.ListProperty(db.Key) #ndb.KeyProperty(repeated=True)
    blobs = db.ListProperty(db.BlobKey)  #ndb.BlobProperty(repeated=True)
    videos = db.ListProperty(db.BlobKey)
    hasvideo = db.BooleanProperty(default=False,
                                   verbose_name='has_video')
    primary_image = blobstore.BlobReferenceProperty()
    usr = db.ReferenceProperty()  # ndb_model.KeyProperty()
    ndb_usr = ndb.KeyProperty()
    hasimages = db.BooleanProperty(default=False,
                                   verbose_name='has_images')
    trending = db.BooleanProperty(default=False,
                                   verbose_name='trending')
    userID = db.StringProperty(verbose_name='User ID')
    integer_price = db.IntegerProperty()
    ip = ndb.StringProperty(verbose_name='ip')
    ipcountry = db.StringProperty(indexed=False, verbose_name='origin')
    tags = db.ListProperty(db.Category)
    category = db.CategoryProperty(verbose_name='Category')
    title = db.StringProperty(verbose_name='title')  # required
    type = db.StringProperty(verbose_name='ContentType')  # sell,wanted,rent,lease,buy
    company_ad = db.BooleanProperty(default=False,
                                    verbose_name='company_ad')  # false or nothing
    user = db.UserProperty(verbose_name='userid')
    im = db.IMProperty(verbose_name='nickname')  # optional, xmpp
    city = db.StringProperty()  # postaladdress should work instead
    region = db.StringProperty()  # postaladdress should work instead
    url = db.StringProperty(verbose_name='url')
    geopt = db.GeoPtProperty(verbose_name='geopt')
    text = db.TextProperty(verbose_name='text')
    currency = db.StringProperty(choices=(
        'INR',
        'EUR',
        'ARS',
        'AUD',
        'BRL',
        'GBP',
        'CAD',
        'CZK',
        'DKK',
        'HKD',
        'HUF',
        'ILS',
        'JPY',
        'MXN',
        'NZD',
        'NOK',
        'PLN',
        'PHP',
        'SGD',
        'SEK',
        'SGD',
        'CHF',
        'USD',
        'THB',
        'TWB',
    ), verbose_name='Currency')
    price = db.StringProperty(verbose_name='price')
    phonenumber = db.PhoneNumberProperty(indexed=False,
                                         verbose_name='phonenumber')  # viewbit
    phoneview = db.BooleanProperty(default=False,
                                   verbose_name='phoneview')
    email = db.EmailProperty(verbose_name='Email')  # optional
    name = db.StringProperty(verbose_name='Name')
    published = db.BooleanProperty(default=True,
                                   verbose_name='published')
    address = db.StringProperty(verbose_name='address')
    number_of_rooms = db.IntegerProperty()
    size = db.FloatProperty()
    regdate = db.IntegerProperty()
    mileage = db.IntegerProperty()
    added = db.DateTimeProperty(verbose_name='added', auto_now_add=True)  # readonly
    modified = db.DateTimeProperty(verbose_name='modified',
                                   auto_now_add=True)
    last_modified = db.DateTimeProperty(required=True, auto_now=True)
    crypted_password = db.StringProperty()  # set default true random
    salt = db.StringProperty()  # merge with passwrd, set default true random or why even store?
    timestamp = db.DateTimeProperty(auto_now=True)  #
    image_url = db.URLProperty();

    def __unicode__(self):
        return self.title

    def to_json(self):
        data = {}
        for prop in self.properties().values():
            data[prop.name] = prop.get_value_for_datastore(self)
        return json(data)

    def __encrypt(self, plaintext, salt=''):
        """returns the SHA1 hexdigest of a plaintext and salt"""

        phrase = hashlib.sha1()
        phrase.update('%s--%s' % (plaintext, salt))
        return phrase.hexdigest()

    def set_password(self, new_password):
        """sets the crypted_password"""

        if not self.salt:
            self.salt = self.__encrypt(str(datetime.now()))
        self.crypted_password = self.__encrypt(new_password, self.salt)

    def set_geography(self):
        """sets the ad's region and city"""

        url = 'http://maps.googleapis.com/maps/api/geocode/json' \
              + '?latlng={},{}&sensor=false'.format(self.geopt.lat,
                                                    self.geopt.lon)
        result = urlfetch.fetch(url)
        jsondata = json.loads(result.content)

        for result in jsondata['results']:
            for component in result['address_components']:
                if 'administrative_area_level_1' in component['types']:
                    self.region = component['long_name'
                    ].replace('County', '')
                if 'locality' in component['types']:
                    self.city = component['long_name']
        if self.city and self.region:
            self.place = self.city + ', ' + self.region
        elif self.city:
            self.place = self.city
        elif self.region:
            self.place = self.region

    def check_password(self, plaintext):
        return self.__encrypt(plaintext, self.salt) \
               == self.crypted_password

    def next(self):
        return (Ad.all().filter('published =', True).filter('modified >'
                                                            , self.modified).get() if Ad.all().filter('published ='
                                                                                                      , True).filter(
            'modified >',
            self.modified).get() else self)

    def prev(self):
        return Ad.all().filter('published =', True).filter('modified <'
                                                           , self.modified).get()

    def get_city(self):
        return montaomodel.City.get(self.cities[0])

    #def get_categoryname(self):
    #    return CATEGORIES[str(ad.category)]

    def get_adimage_serving_url(self):
        data = memcache.get('img-serv-url' + str(self.key().id()))
        if data is not None:
            return data
        else:
            if self.matched_images.get():
                try:
                    data = images.get_serving_url(str(self.matched_images.get().primary_image.key()), size=150).replace('http://', 'https://')
                except Exception, e:
                    logging.exception('exception: %s', str(e))
                    data = False
            else:
                data = False
            memcache.add('img-serv-url' + str(self.key().id()), data, 36000)
            return data

    def uri2view(self):
        try:
            return self.get_adimage_serving_url()
        except Exception, e:
            logging.exception('exception: %s', str(e))
            return None

    @classmethod
    def count_all(cls):
        """
        Count *all* of the rows (without maxing out at 1000)
        """

        count = 0
        query = cls.all().order('__key__')

        while True:
            current_count = query.count()
            if current_count == 0:
                return count
            count += current_count

            if current_count == 1000:
                last_key = query.fetch(1, 999)[0].key()
                query = query.filter('__key__ > ', last_key)

        return count
    
posta Niklas Rosencrantz 01.04.2018 - 03:01
fonte

2 risposte

2

Scelgo l'eredità. Dal momento che non è necessario creare un modello pubblicitario diverso per le auto, l'utilizzo di una classe figlia aiuterà questa classe di annunci a non creare più confusione. Da quello che vedo nel tuo codice, la classe originale racchiude dati con proprietà diverse, ed è stato difficile per me seguire i campi che usi. Capisco che questo è un sistema di produzione, ma devo essere d'accordo con Robert, l'utilizzo di un programma di mappatura degli oggetti renderebbe più facile per te vedere il tuo modello di dati in modo più chiaro. E mi chiedo se sarebbe più facile migliorare e mantenere se avessi più classi. In questo modo puoi separare la sezione pubblicitaria dai dati delle informazioni sul veicolo. Oppure potresti davvero separarli con le classi Pubblicità, RV e Auto / Veicolo

    
risposta data 04.04.2018 - 08:50
fonte
1

Suggerisco di utilizzare invece la decorazione (non i decoratori di Python, ma il motivo di progettazione Decorator), o solo la delega. Altrimenti, alla fine raggiungerai un punto in cui i livelli di ereditarietà sono così profondi e il codice duplicato è così onnipresente che è impossibile da mantenere.

Avere un modello semplice e generico come base e quindi aggiungere tali campi / comportamenti decorandolo.

    
risposta data 04.04.2018 - 11:35
fonte

Leggi altre domande sui tag