2016-03-22 3 views
1

Ich habe eine Datenbank (und Modell) Situation wie in dem folgenden Schema gezeigt zu verhindern:save() verboten Datenverlust aufgrund nicht gespeicherten verwandten Objekt 'postid'

diese Database diagram

die ModelSerialize ist:

class PostCreateSerializer(serializers.ModelSerializer): 
    base64image = serializers.CharField(allow_blank=True, required=False) 
    categories = serializers.ListField(child=serializers.IntegerField(), required=False) 

    class Meta: 
     model = Post 
     fields = ('title', 'text', 'base64image', 'categories') 

    def create(self, validated_data): 
     cats = None 
     if 'categories' in validated_data: 
      cats = validated_data.pop('categories') 

     post = Post.objects.create(**validated_data) 

     if cats is not None: 
      for cat in cats: 
       PostCategory.objects.create(postid=post, categoryid=Category.objects.get(id=cat), isprimary=False) 

     return post 

ich sende diese json an die api Methode

{ 
"title": "Post Test", 
"text": "Body post Test", 
"categories": [2,4] 
} 

, aber ich habe diesen Fehler:

ValueError: save() prohibited to prevent data loss due to unsaved related object 'postid'. 

Internal Server Error: /api/post/create/ 
Traceback (most recent call last): 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response 
    response = self.process_exception_by_middleware(e, request) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response 
    response = wrapped_callback(request, *callback_args, **callback_kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view 
    return view_func(*args, **kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/views/generic/base.py", line 68, in view 
    return self.dispatch(request, *args, **kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/views.py", line 466, in dispatch 
    response = self.handle_exception(exc) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/views.py", line 463, in dispatch 
    response = handler(request, *args, **kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/generics.py", line 192, in post 
    return self.create(request, *args, **kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/mixins.py", line 21, in create 
    self.perform_create(serializer) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/server/rumorize/contents/views.py", line 117, in perform_create 
    PostCategory.objects.create(postid=x, categoryid=Category.objects.get(id=cat), isprimary=False) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/manager.py", line 122, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/query.py", line 401, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/base.py", line 651, in save 
    "unsaved related object '%s'." % field.name 
ValueError: save() prohibited to prevent data loss due to unsaved related object 'postid'. 

Meine post_create Umsetzung im Blick:

def perform_create(self, serializer): 
# build and save the image 
if 'base64image' in serializer.validated_data: 
    base64_string = serializer.validated_data.pop('base64image') 
    import base64 
    import os 
    import uuid 

    base64_format, base64_string = base64_string.split(';base64,') 
    base64_content = base64.b64decode(base64_string) 
    filename = '{}{}'.format(uuid.uuid4(), utilities.file_extension_from_base64_format(base64_format)) 
    path = os.path.join(MEDIA_ROOT, 'post_photos') 

    if not os.path.exists(path): 
     os.makedirs(path) 

    with open(os.path.join(path, filename), 'wb+') as f: 
     f.write(base64_content) 

    serializer.validated_data['image'] = filename 

serializer.save(userid=self.request.user, updateuserid=self.request.user, state=1) 

UPDATE

jetzt habe ich diesen Fehler: django.db.models.fields.related_descriptors .RelatedObjectDoesNotExist: Post hat keine ID.

das sind meine Modelle:

class Post(models.Model): 
id = models.BigIntegerField(db_column='ID', primary_key=True, editable=False) 
title = models.CharField(db_column='Title', max_length=500) 
text = models.TextField(db_column='Text') 
createdate = models.DateTimeField(db_column='CreateDate', editable=False, default=datetime.datetime.now) 
updatedate = models.DateTimeField(db_column='UpdateDate', blank=True, null=True, editable=False, default=datetime.datetime.now) 
updateuserid = models.ForeignKey(User, models.DO_NOTHING, db_column='UpdateUserID', blank=True, null=True, related_name='PostUpdateUser') 
userid = models.OneToOneField(User, models.DO_NOTHING, db_column='UserID', related_name='creation_user') 
image = models.CharField(db_column='Image', max_length=500, blank=True, null=True) 
state = models.SmallIntegerField(db_column='State') 

class Meta: 
    managed = False 
    db_table = 'post' 
    verbose_name = 'Post' 
    verbose_name_plural = 'Posts' 

Klasse PostCategory (models.Model): id = models.BigIntegerField (db_column = 'ID', primary_key = True) # Feldname aus Kleinbuchstaben. postid = models.ForeignKey (Beitrag, models.DO_NOTHING, db_column = 'PostID', related_name = 'posts_categories') # Feldname in Kleinbuchstaben geschrieben. categoryid = models.ForeignKey (Kategorie, models.DO_NOTHING, db_column = 'CategoryID') # Feldname in Kleinbuchstaben geschrieben. isprimary = models.BooleanField (db_column = 'IsPrimary') # Feldname in Kleinbuchstaben geschrieben. Dieser Feldtyp ist eine Schätzung.

class Meta: 
    managed = False 
    db_table = 'post_category' 

irgendwelche Vorschläge? Danke

+0

Es fühlt sich an, als würde Ihr Code hier nicht mit dem Fehler übereinstimmen. Sie erhalten den Fehler, weil der Post gespeichert wurde, der dem Post.objects.create widerspricht. – Linovia

+0

würdest du besser erklären, was meinst du? – alfdev

+0

Wenn mein Ansatz nicht der richtige ist, bitte sagen Sie mir, wie ich Post-Instanz und verwandte Kategorien speichern kann? – alfdev

Antwort

1

Versuchen Sie, die create Methode von ModelSerializer aufzurufen, anstatt das Objekt selbst zu erstellen. Auch die if-Anweisung ist nicht notwendig und für PostCategory können Sie die id Felder direkt verwenden.

class PostCreateSerializer(serializers.ModelSerializer): 
    base64image = serializers.CharField(allow_blank=True, required=False) 
    categories = serializers.ListField(child=serializers.IntegerField(), required=False) 

    class Meta: 
     model = Post 
     fields = ('title', 'text', 'base64image', 'categories') 

    def create(self, validated_data): 

     # you don't need the if block 
     cats = validated_data.pop('categories', None) 

     # try calling the create method of ModelSerializer 
     post = super(PostCreateSerializer, self).create(validated_data) 

     if cats is not None: 
      for cat in cats: 
       PostCategory.objects.create(postid_id=post.id, categoryid_id=cat, isprimary=False) 

     return post 
+0

Es tut mir leid, aber ich bekomme den gleichen Fehler. – alfdev

+0

Verwenden Sie Transaktionen? – ilse2005

+0

Nein, ich verwende keine Transaktionen – alfdev