2015-11-19 4 views
0

У меня есть две модели: одна для создания названия и одна для создания голосования за это название.Модель Django дублируется от модели foreignkey

Когда я создаю более одного голоса по одному и тому же заголовку, я получаю дубликаты названий, и я не могу понять, почему.

Вот моя модель голос,

class Vote(GenericModel): 
    """ 
    Model for vote on a title 
    """ 
    title = models.ForeignKey(Title, blank=True, related_name='votes') 

    user = models.ForeignKey(ArtLover, blank=True) 

    def __str__(self): 
     return _("vote on {}").format(self.title.__str__()) 

и вид на голосование:

@detail_route(methods=['post']) 
def vote(self, request, *args, **kwargs): 
    """ 
    Create vote for a title 
    """ 
    title = Title.objects.get(text=kwargs.get('text')) 
    user = ArtLover.objects.get(id=request.user.id) 

    if title.user.id == user.id: 
     return Response(
      _("You can't vote for your own title"), 
      status=status.HTTP_403_FORBIDDEN 
     ) 

    if Vote.objects.filter(title=title, user=user).exists(): 
     return Response(
      _("Vote already exists"), 
      status=status.HTTP_409_CONFLICT 
     ) 

    vote = Vote.objects.create(title=title, user=user) 

    return Response({ 
     'vote': VoteSerializer(vote).data 
    }, status=status.HTTP_201_CREATED) 

Если я печатаю количество экземпляров заголовка после создания голосования, подсчет не хорошо, не дублировать , поэтому я предполагаю, что дублирование произойдет позже. Можете ли вы указать мне, где/почему происходит дублирование?

Когда я удаляю голосование, название, созданное дублированием, также удаляется.

Edit 1:

Я попытался создать собственный менеджер для моделей титульных блокировать дублирование, но когда дублирование произойдет при создании голосования, менеджер названия не называются.

Когда я сравниваю первичный ключ экземпляра исходных моделей с дублированием, они одинаковы.

Edit 2:

пытается упорядочить поля названия в художественных произведений сериализатором

мои работы сериализатору:

class ArtworkDetailSerializer(serializers.ModelSerializer): 
    """ 
    Detailed serializer for Artwork 
    """ 
    artist = serializers.CharField(source='artist.username', read_only=True) 
    titles = TitleSerializer(many=True) 
    emotions = serializers.SerializerMethodField() 

    class Meta: 
     model = Artwork 
     fields = ('id', 'file', 'artist', 'index', 'url', 'titles', 'emotions') 
     read_only_fields = ('id', 'artist', 'index', 'url', 'titles', 'emotions') 

мой титул сериализатору:

class TitleSerializer(serializers.ModelSerializer): 
    """ 
    Serializer for title suggested by user 
    """ 
    votes = VoteSerializer(many=True, read_only=True) 
    user = serializers.CharField(source='user.username', read_only=True) 
    artwork = serializers.CharField(source='artwork.url', read_only=True) 

    class Meta: 
     model = Title 
     fields = ('id', 'artwork', 'text', 'user', 'votes',) 
     read_only_fields = ('id', 'artwork', 'user', 'votes',) 

мои работы Вид:

class ArtworkView(viewsets.ModelViewSet): 
    """ 
    View that handle Artwork 
    """ 
    lookup_field = 'url' 
    queryset = Artwork.objects.all() 
    permission_classes = (
     permissions.IsAuthenticatedOrReadOnly, 
     IsArtistOrReadOnly, 
    ) 

    def get_serializer_class(self): 
     if self.action == 'retrieve': 
      return ArtworkDetailSerializer 
     return ArtworkSerializer 
+0

Нет названия не создаются вообще в коде у вас есть показано на рисунке. Как вы думаете, почему здесь создается дубликат? – Alasdair

+0

Поскольку название дублируется, когда я создаю голосование, и в моем тесте это код, который я выполняю, поэтому я предполагаю, что django делает дублирование самостоятельно – bboumend

+0

Пожалуйста, покажите свой тестовый код. Я не вижу, как код выше будет создавать какие-либо заголовки, если у вас нет сигналов или переопределенных методов, которые вы нам не показывали. – Alasdair

ответ

0

Вы можете попробовать заменить:

vote = Vote.objects.create(title=title, user=user)

в

vote, created = Vote.objects.get_or_create(title=title, user=user)

+0

не решает проблему, ее название, которое дублируется не голосованием – bboumend

0

Probleme доносился из моих моделей названия:

class Title(GenericModel): 
    """ 
    Model for title suggested by user 
    """ 
    class Meta: 
     ordering = ['votes'] 

    text = models.CharField(_('text'), max_length=255) 

    artwork = models.ForeignKey(Artwork, blank=True, related_name='titles') 

    user = models.ForeignKey(ArtLover, blank=True) 

    def __str__(self): 
     return self.text 

упорядочения в мета был дуп разрешать модель каждый раз, когда я голосую, почему это происходит? и как я предполагаю заказать свой титул по количеству голосов, которое они получают?

1

При заказе в соответствующем поле votes это заставляет Django выполнять левое внешнее соединение. Если заголовок связан с несколькими голосами, он возвращается в наборе запросов один раз для каждого голосования.

Обратите внимание, что сохранение голосов не создает дубликатов. Вы можете подтвердить это, заказав другое поле и проверив счет.Как вы говорите в своем вопросе, первичный ключ дубликатов одинаковый, поэтому вы не создали дополнительных заголовков в базе данных, набор запросов просто возвращает одни и те же заголовки несколько раз.

Title.objects.order_by('pk').count() 

Чтобы упорядочить по количеству голосов, вам нужно аннотировать QuerySet с числом голосов, то порядка по аннотации:

Title.objects.annotate(num_votes=Count('votes')).order_by('num_votes') 
+0

Спасибо за объяснение, за заказ этой работы, но я не делаю никакого запроса на отправку данных, im используя сериализатор, знаете ли вы, как применять этот заказ на уровне модели или сериализатора? (я использую вложенный сериализатор) – bboumend

+0

Вы не показывали свой сериализатор или как его используете, поэтому я не могу сказать, как установить там запрос. Вы можете создать настраиваемый менеджер и переопределить ['get_queryset'] (https://docs.djangoproject.com/en/1.8/topics/db/managers/#modification-initial-manager-querysets), но это не очень хорошая идея. потому что это будет означать, что вы делаете аннотацию для всех запросов, даже если вам это не нужно. – Alasdair

+0

Я думаю, что всякая аннотация для меня может быть хорошей, я могу изменить свой исходный пост с помощью своего сериализатора, если вы хотите взглянуть, я попытался добавить пользовательский запрос в поля заголовков, чтобы заказать их без успеха. Также я мог бы сделать SerializerMethodField, но это кажется излишним? – bboumend

Смежные вопросы