Как создать метод сохранения в абстрактной модели, который проверяет, существует ли экземпляр? - PullRequest
0 голосов
/ 18 октября 2019

У меня есть следующие модели:

class PlaceMixin(models.Model):    
    name = models.CharField(max_length=200, null=True, blank=True)
    address = models.CharField(max_length=200, null=True, blank=True)
    sublocality = models.CharField(max_length=100, null=True, blank=True)
    city = models.CharField(max_length=100, null=True, blank=True)

    class Meta:
        abstract = True

class Bar(PlaceMixin):
   pass

class Restaurant(PlaceMixin):
   pass

В баре и ресторане почти одинаковый метод save ():

def save(self, *args, **kwargs):
    try:
        bar = Bar.objects.get(address=self.address)

    except Bar.DoesNotExist:
         Do something
    super().save(*args, **kwargs)

def save(self, *args, **kwargs):
    try:
        restaurant = Restaurant.objects.get(address=self.address)

    except Restaurant.DoesNotExist:
         Do something
    super().save(*args, **kwargs)

Мне было интересно, смогу ли я поместить метод в Abstractмодель и передать ее двум унаследованным моделям?

def save(self, *args, **kwargs):
    try:
        temp = self.objects.get(address=self.address)

    except self.DoesNotExist:
         Do something
    super().save(*args, **kwargs)

Как-то так? Но вы можете запросить в абстрактной модели. Мне нужно проверить, существует ли экземпляр для выполнения действия.

Ответы [ 2 ]

0 голосов
/ 18 октября 2019

Вы можете создать общий метод сохранения для моделей Restaurant и Bar в классе Mixin следующим образом:

from django.apps import apps

class CommonMixin(object):
     def save(self, *args, **kwargs): 
        if self.__class__.__name__ == "Resturant":
             model = apps.get_model('app_name', 'Bar')    
             if model.objects.filter(address=self.address).exists():
                     ...
        else:
            model = apps.get_model('app_name', 'Restaurant')    
             if model.objects.filter(address=self.address).exists():
                     ...
        super(CommonMixin, self).save(*args, **kwargs)

И импортировать его в классы Restaurant и Bar:

 class Restaurant(CommonMixin, PlaceMixin):
     ...

 class Bar(CommonMixin, PlaceMixin):
     ...

Вероятно, лучшим подходом является использование отдельной модели для информации об адресе. Тогда вам не понадобится новый Mixin, чтобы переопределить сохранение (подход, описанный выше, похож на чрезмерный инжиниринг). Допустим, у вас есть другая модель адреса, там вы можете просто поставить unique=True, чтобы ограничить повторяющиеся записи:

class Address(models.Model):
     address = models.CharField(max_length=255, unique=True)


class PlaceMixin(models.Model):
     address = models.ForeignKey(Address)
     ...
0 голосов
/ 18 октября 2019

Вы можете использовать abstract метаданные для достижения этой цели. И если вы хотите использовать какую-либо переменную внутри модели класса, вам просто нужно использовать self.__class__ примерно так:

class PlaceMixin(models.Model):    
    name = models.CharField(max_length=200, null=True, blank=True)
    address = models.CharField(max_length=200, null=True, blank=True)
    sublocality = models.CharField(max_length=100, null=True, blank=True)
    city = models.CharField(max_length=100, null=True, blank=True)

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        try:
            self.__class__.objects.get(address=self.address)
        except self.__class__.DoesNotExist:
            # Do something
        else:
            super().save(*args, **kwargs)


class Bar(PlaceMixin):
   pass

class Restaurant(PlaceMixin):
   pass

В исходном коде Django много такого дизайна кода, много хорошегопрактики в их проекте, так что попробуйте. Например: строка кода в репозитории Django

...