I am learning Django and doing some project where I have three models with following relationships:
#models.py
class Model1(models.Model):
status = models.CharField(max_length = ....)
class Model2(models.Model):
model1 = models.ForeignKey(Model1, ....)
name = models.CharField(max_length = ....)
class Model3(models.Model):
model2 = models.ForeignKey(Model2, ....)
name = models.CharField(max_length = ....)
I want to update status field in my Model1 based on the logic which happens in my views.py on Model3 instance i.e.
views.py
def model3_view(request, pk):
model1 = get_object_or_404(Model1, pk=pk)
model3 = Model3.objects.filter(model1_id=model1.pk)
my logic goes here....
if <my logic outcome> == True:
model1_status = Model1.objects.update_or_create(status='closed', pk=model1.pk)
However, I am getting error UNIQUE constraint failed: model1_model1.id.
I tried to reference my model2 instance pk and it does work fine i.e. model1_status = Model1.objects.update_or_create(status='closed', pk=model2.pk) but could not figure out how I can do this for 1 level up i.e. for model1 pk...
The Unique error is most likely because the update_or_create is just trying to create and then getting conflicting primary keys.
Because you are already getting Model1 here: model1 = get_object_or_404(Model1, pk=pk) you could just replace the update_or_create with:
model1.status = 'closed'
model1.save()
Note: I didn't originally post this as an answer because I wasn't sure if update_or_create was mandatory or not.
Related
I have an entity model, and i want to list all the instances of Entity based on the id of a category instance in it. So basically i'd like to list all the Entity instances with category id of 1 with /specialists/category/1 but for some reason i get
Not Found: /api/v1/specialists/categories/1
Even though the code looks alright.
class Entity(models.Model):
entity_category = models.ManyToManyField(Category)
class SpecialistSerializer(serializers.ModelSerializer):
entity_category = SpecialistCategorySerializer(read_only=True, many=True)
class Meta:
model = Entity
fields = (....., entity_category)
class SpecialistsPerCategory(generics.ListAPIView):
serializer_class = SpecialistSerializer
def get_queryset(self):
category_id = self.kwargs['pk']
return Entity.objects.filter(entity_category=category_id, lookup_type='in')
path('specialists/category/<int:pk>', SpecialistsPerCategory.as_view()),
Do you have any idea what's wrong?
You have category in path, but plural categories in url.
Also I think that will not work, because SpecialistSerializer have model of Entity, but you want to get pk of Category in SpecialistsPerCategory that is based on that serializer.
I am trying to make custom serializer work. Can't use model serializer since I will be saving data into multiple models. Here is my code:
class RushSerializer(serializers.Serializer):
keyword = serializers.IntegerField(read_only=True)
url = serializers.URLField()
def save(self):
keyword = self.validated_data['keyword']
url = self.validated_data['url']
Url1.objects.create(keyword=keyword, url=url)
And I input data like this:
nov = {'url': 'https://domain.com/'}
nov['keyword'] = id
serializer = RushSerializer(data=nov)
It returns me this error:
KeyError at /admin/keywords/kw/add/
'keyword'
Here is the model itself:
class Url1(models.Model):
keyword = models.ForeignKey(KW)
url = models.URLField()
What is wrong with my code? I tried pretty much anything from here but can't seem to make it work.
EDIT: To clarify, it works if I do it with model serializer and this:
class Meta:
model = Url1
fields = ('keyword', 'url')
So problem isn't in input 100% but in serializer itself.
If I do keyword without read_only then I get this error:
ValueError at /admin/keywords/kw/add/ Cannot assign "104":
"Url1.keyword" must be a "KW" instance.
I'm attempting to add a new foreign key to an existing model of mine, but I'm having issues getting it to save the values from the UI. When I get to the relevant page, the data populates correctly, but when I attempt to save a change of the foreign key I get a 1054 "Unknown column 'schedule_id' in 'field list'" error. Strangely, if I refresh the page, the changes were saved regardless of the error.
Relevant models:
class Group(BaseModel):
code = CharField()
name = CharField()
calendar = models.ForeignKey(Calendar)
schedule = models.ForeignKey(Schedule, null=True, blank=True, default=None) # this is the new FK
class Schedule(BaseModel):
code = CharField()
name = CharField()
description = CharField()
#various integer fields
I'm using South for my database migrations:
def forwards(self, orm):
db.add_column('group', 'schedule',
self.gf('django.db.models.fields.related.ForeignKey')\
(to=orm['app.Schedule'], blank=True, null=True)\
)
The view is pretty simple:
def api_group(jsonDict, request):
if request.method == "POST":
#other handlers
elif operation == "edit":
_update_group(request)
def _update_group(request):
group = Group.objects.get(id=request.POST.get('id'))
formData = request.POST.copy()
form = GroupForm(formData, instance=group)
if form.is_valid():
form.save()
class GroupForm(renderutils.BaseModelForm):
id = forms.CharField(widget=forms.HiddenInput())
class Meta(renderutils.BaseModelForm.Meta):
model = Group
When I look at the 'group' table, I can see the field named 'schedule_id' and correct values are getting assigned on save, I just don't understand why the error is being raised if nothing is going wrong? I've tried doing a backward and forward south migration multiple times to make sure it wasn't something wrong with it.
What i'm trying to do is to add a query result from a model to a modelresource, as you can see in this block of code:
def dehydrate(self, bundle):
bundle.data['image'] = place_image.image.get(place=1).get(cardinality=0)
I want to add a field to PlaceResource that will contain the image from place_site model where place=1 and cardinality=0. But im recieving an error:
The 'image' attribute can only be accessed from place_image instances
So, my question is: Is it impossible to use the query result from another model in a tastypie modelresource? Im sorry for my bad english, please correct me if something's wrong. Thanks for your time.
There's the complete code:
MODELS.py:
class place(models.Model):
idPlace = models.AutoField(primary_key=True)
Name = models.CharField(max_length=70)
class place_image(models.Model):
idImage = models.AutoField(primary_key=True)
place = models.ForeignKey(place,
to_field='idPlace')
image = ThumbnailerImageField(upload_to="place_images/", blank=True)
cardinality = models.IntegerField()
API.py
from models import place
from models import place_image
class PlaceResource(ModelResource):
class Meta:
queryset = place.objects.all()
resource_name = 'place'
filtering = {"name": ALL}
allowed_methods = ['get']
def dehydrate(self, bundle):
bundle.data['image'] = place_image.image.get(place=1).get(cardinality=0)
return bundle
class PlaceImageResource(ModelResource):
place = fields.ForeignKey(PlaceResource, 'place')
class Meta:
queryset = place_image.objects.all()
resource_name = 'placeimage'
filtering = {"place": ALL_WITH_RELATIONS}
allowed_methods = ['get']
The error you are getting is caused by the fact that you are accessing the image attribute of a model class, not instance.
The object that is being dehydrated in the dehydrate method is stored in obj attribute of the bundle parameter. Also, you are trying to filter place_image models to only those with place=1 and cardinality=0 by accessing the image attribute of place_image model class. Such filtering won't work as image is not a ModelManager instance. You should use objects attribute instead. Furthermore, get() method returns an actual model instance thus a subsequent call to get() will raise AtributeError as your place_image model instances have no attribute get.
So, all in all, your dehydrate should look like this:
def dehydrate(self, bundle):
bundle.data['image'] = place_image.objects.get(place_id=1, cardinality=0).image
return bundle
Notice that this code requires the place_image with desired values to exist, otherwise a place_image.DoesNotExist will be thrown.
There is also some redundancy in your models:
idPlace and idImage can be removed, as django by default creates an AutoField that is a primary key called id when no other primary key fields are defined
place_image.place field has a redundant to_field parameter, as by default ForeignKey points to a primary key field
Can I get type of related field from a model queryset?
Let consider example model:
class Semester(models.Model):
active = models.BooleanField(default=False, verbose_name="Active")
class Subject(models.Model):
name = models.CharField(max_length=100, verbose_name="Name")
semester = models.ForeignKey(Semester, verbose_name="Semester")
if I have some field name in variable and queryset I can do this:
querySet = Subject.objects.all()
some_field_name = 'name'
field_type = querySet.model._meta.get_field(some_field_name).get_internal_type()
Is there any way to get related field type, for example:
querySet = Subject.objects.all()
some_field_name = 'semester__active'
field_type = ?
Try using get_field_by_name:
field_type = querySet.model._meta.get_field_by_name(some_field_name).get_internal_type()
From Django's source code:
def get_field_by_name(self, name):
"""
Returns the (field_object, model, direct, m2m), where field_object is
the Field instance for the given name, model is the model containing
this field (None for local fields), direct is True if the field exists
on this model, and m2m is True for many-to-many relations. When
'direct' is False, 'field_object' is the corresponding RelatedObject
for this field (since the field doesn't have an instance associated
with it).
Uses a cache internally, so after the first access, this is very fast.
"""
Also try:
field = querySet.model._meta.get_field_by_name("semester")
field_type = field[0].rel.to._meta.get_field_by_name("active").get_internal_type()
Thanks for any help!
I find solution with some help from this answer:
main, related = some_field_name.split("__")
field_type = querySet.model._meta.get_field(main).rel.to._meta.get_field(related).get_internal_type()