Django foreign key question - python

All,
i have the following model defined,
class header(models.Model):
title = models.CharField(max_length = 255)
created_by = models.CharField(max_length = 255)
def __unicode__(self):
return self.id()
class criteria(models.Model):
details = models.CharField(max_length = 255)
headerid = models.ForeignKey(header)
def __unicode__(self):
return self.id()
class options(models.Model):
opt_details = models.CharField(max_length = 255)
headerid = models.ForeignKey(header)
def __unicode__(self):
return self.id()
AND IN MY VIEWS I HAVE
p= header(title=name,created_by=id)
p.save()
Now the data will be saved to header table .My question is that for this id generated in header table how will save the data to criteria and options table..Please let me know..
Thanks..

Given your:
p= header(title=name,created_by=id)
p.save()
You can now:
c=criteria(details='some details', headerid=p)
c.save()
o=options(opt_details='more details', headerid=p)
o.save()
Hope this helps.

Take advantage of <related>_set query managers, it's clearer and shorter than constructing and saving objects in separate operations.
h = header.objects.create(title=name,created_by=id)
c = h.criteria_set.create(details='some details')
o = h.options_set.create(opt_details='more details')
And some offtopic: please, start class names from uppercase letter, it really makes code easier to read.

Related

Create multiple entries for one model in a Django modelform

Sorry if the title is confusing, I can't really think of how else to word it.
I am creating a site where there are many quizzes. Each Quiz model
class Quiz(models.Model):
name = models.CharField(max_length = 80)
description = models.CharField(max_length = 300)
num_questions = models.IntegerField(default = 10)
slug = models.SlugField(max_length = 20)
img = models.URLField(blank = True) # allow it to be none
def __str__(self):
return self.name
def get_questions(self):
return self.question_set.all()
looks like this... and it has some attributes like name, description, etc. There are many Question models that have ForeignKey to one Quiz:
class Question(models.Model):
quiz = models.ForeignKey(Quiz, on_delete = models.CASCADE)
img = models.URLField(blank = True) # allow none`
content = models.CharField(max_length = 200)
def __str__(self):
return self.content
def get_answers(self):
return self.answer_set.all()
and then there are some Choice models that have ForeignKey to one Question:
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete = models.CASCADE)
content = models.CharField(max_length = 200)
correct = models.BooleanField(default = False)
Now. I want to create one single ModelForm from which I can create 1 quiz record, and then 10 question records with 4 choice records per question. It would be very nice if they could automatically set their foreignkey to the Question that is being created. How can I go about this? Is it even possible? I don't even know if my wording of this question is making sense because I have a great big idea in my head but no idea how to express it properly in words or code.
Help is appreciated :)
If you have 3 models and you want to show them in a single form in your HTML file. Then you can simply create a model form for each of them and add them in a single <form> tag.
The answer to a similar question is posted here.
If you mean inserting multiple records at the same time, then consider looking at formset factory - https://docs.djangoproject.com/en/3.2/topics/forms/formsets/

Django Models,There's a column in the table, but it cannot be referenced from this part of the query,

I've defined some models in django and I can successfully add data to them using objects in django but the problem is that when I try to do this directly from the database it gives me this "HINT" There's a column named origin_id in the table flight, but it cannot be referenced from this part of the query, I'm using postgresql for the database, So can anyone please help me with this? I know there are similar questions like this but I couldn't find the solution.
class AirportManager(models.Manager):
#classmethod
def ret(cls):
return 'This is a custom "Manager"'
#classmethod
def code(cls):
obj = Airport.objects.all()
return obj
class Airport(models.Model):
code = models.CharField(max_length = 3)
city = models.CharField(max_length = 20)
objects = AirportManager()
class Meta:
db_table = 'airport'
def __str__(self):
return f"{self.city} ({self.code})"
class Flight(models.Model):
origin = models.ForeignKey(Airport,on_delete=models.CASCADE)
destination = models.ForeignKey(Airport,on_delete=models.CASCADE,related_name = "arrivals")
duration = models.IntegerField()
flights = models.Manager()
class Meta:
db_table = 'flight'
def __str__(self):
return f'from "{self.origin}" to "{self.destination}" in "{self.duration}" hrs'

How can I make DRF Serializer create() function only create an entry that does not exist yet?

I have two tables, which are connected with each other through a cross table. (Recipes <--> Ingredients)
My Serializer works ok, I can send POST-Requests and it saves everything. The problem ist, that every time a new Recipe comes in with let just say the Ingredient "Milk" then my Serializer creates a new entry in my database named Milk, although I have an already existing entry "Milk" in my database.
How do I tell my Serializer to use the Id of an already existing entry instead of creating a new one every time for the cross table.
Here is how I thought I could fix it, but it clearly doesn't:
class RecipeIngredientSerializer(serializers.ModelSerializer):
ingredient = IngerdientSerializer()
class Meta:
model = recipe_ingredients
fields = ['amount', 'unit', 'ingredient']
def create(self, validated_data):
ingredient_validated_data = validated_data.pop('ingredient')
ingredient_serializer = self.fields['ingredient']
ingredientDict = dict(ingredient_validated_data)
// This is where I try to check if there is already an ingredient with the name from the form
ingredientObj = ingredient.objects.all().filter(ingredient_name=ingredientDict['ingredient_name']).
if not ingredientObj:
ingredient_instance = ingredient.objects.create(**ingredientDict)
validated_data['ingredient'] = ingredient_instance
else:
ingredient_instance = ingredient_serializer.create(ingredientDict)
validated_data['ingredient'] = ingredient_instance
recipe_ingredients_instance = recipe_ingredients.objects.create(**validated_data)
return recipe_ingredients_instance
This code also seems to work, at least I find an existing ingredient, but after the last create() it seems to ignore what ever I push into the validated_data['ingredient'] object.
EDIT
my models are:
class recipe_ingredients(models.Model):
recipe = models.ForeignKey(recipe, models.CASCADE)
ingredient = models.ForeignKey(ingredient, models.CASCADE)
amount = models.IntegerField(default=0)
unit = models.CharField(max_length=50)
def __str__(self):
return self.ingredient.ingredient_name + ' of Recipe: ' + self.recipe.recipe_name
class recipe(models.Model):
recipe_name = models.CharField(max_length=200)
assembly_time = models.IntegerField(default=0)
number_of_servings = models.IntegerField(default=0)
tags = models.ManyToManyField(tag, blank=True)
def __str__(self):
return self.recipe_name
class ingredient(models.Model):
ingredient_name = models.CharField(max_length=200)
ingredient_calories = models.IntegerField('Calories per 100 Units', default=-1)
default_unit = models.CharField(max_length=50)
def __str__(self):
return self.ingredient_name
I got the answer, finally. My mistake is this line in my Serializer:
ingredientObj = ingredient.objects.all().filter(ingredient_name=ingredientDict['ingredient_name']).
if not ingredientObj:
ingredient_instance = ingredient.objects.create(**ingredientDict)
validated_data['ingredient'] = ingredient_instance
I changed it now so that it looks something like this:
ingredientObj = ingredient.objects.all().filter(ingredient_name=ingredientDict['ingredient_name']).
if len(ingredientObj):
ingredient_instance = ingredientObj.first()
validated_data['ingredient'] = ingredient_instance
The ingredient.object.create(**ingredientDict) does actually create a new object (who would have known ;) ). This is probably still an ugly solution and I am open to more criticism but this does work for now.

Pull object from database in views.py

I would like to create a function in views.py to retrieve an information from this class:
class Vin(models.Model):
def __unicode__ (self):
return self.nom
name = models.CharField( max_length = 30)
year = models.CharField (max_length = 4)
appellation = models.ForeignKey(Appellation)
photo = models.CharField (max_length = 70)
quantity = models.IntegerField ()
released = models.IntegerField()
and retrieve it by its attribute "name".
So for instance, if i have a Wine ("chardonnay", 1990, ...) only retrieve chardonnay.
Thanks !
Your view function will be called after the user enters a URL that is in your urls.py. The url entered may provide you with the additional information you need to query the database and get information on the Vin object you need.
If you want a view to just return every Vin in your database. Something like this might be helpful for you:
def get_vins(request, *args, **kwargs):
vins = Vin.objects.all().values_list('name', flat=True)
return render(request, 'somepage.html', {"vins": vins})
Your question is really vauge and you should read the django documentation. This is a very basic question that all starters should learn.

django views question

In my django views i have the following
def create(request):
query=header.objects.filter(id=a)[0]
a=query.criteria_set.all()
logging.debug(a.details)
I get an error saying 'QuerySet' object has no attribute 'details' in the debug statement
.What is this error and what should be the correct statemnt to query this.And the model corresponding to this is as follows
where as the models has the following:
class header(models.Model):
title = models.CharField(max_length = 255)
created_by = models.CharField(max_length = 255)
def __unicode__(self):
return self.id()
class criteria(models.Model):
details = models.CharField(max_length = 255)
headerid = models.ForeignKey(header)
def __unicode__(self):
return self.id()
Thanks..
QuerySet.all() returns a QuerySet. Index it or iterate over it if you want to access the individual models:
logging.debug(a[0].details)
for m in a:
logging.debug(m.details)

Categories

Resources