Django add recipe form - django

I hope you will give me some advice.
So I can't save Recipe into my database through RecipeCreateForm.
Here is my code:
models.py
class Recipe(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='recipes_created')
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, blank=True)
image = models.ImageField(upload_to='recipes/%Y/%m/%d')
description = models.TextField("Description")
ingredients = models.TextField("Ingredients")
preparation = models.TextField("Preparation")
created = models.DateField(auto_now_add=True, db_index=True)
def __str__(self):
return self.title
forms.py
from django import forms
from .models import Recipe
class RecipeCreateForm(forms.ModelForm):
class Meta:
model = Recipe
fields = ('title', 'image' 'description', 'ingredients', 'preparation')

You are missing an ',' in the forms between 'image' and 'description
This is why the error is 'imagedescription', it is reading both of them as 1 string.
fields = ('title', 'image' 'description', 'ingredients', 'preparation')
with the ',' it will read
fields = ('title', 'image', 'description', 'ingredients', 'preparation')

You need to create a view in views.py file. To create a new object, view will be as shown:
def recipe_create(request):
if request.POST:
form = RecipeCreateForm(request.POST)
new_recipe = form.save() #create a new instance in model form
else:
form = RecipeCreateForm()
context = {'form':form}
template = 'xyz.html'
return render(request, template, context)
If request is post i.e you are saving data from the form to database. And if request is get you are rendering an empty form.

Related

Django Rest Framework ModelViewSet ManyToMany Field override partial_update Method is not working update_or_create

I have a question here
I have two models
Tag Model
class Tag(models.Model):
creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='author')
name = models.CharField(max_length=100)
def __str__(self):
return self.name
Profile Model
class Profile(models.Model):
profiler = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='contour')
bio = models.TextField(blank=True, null=True)
tags = models.ManyToManyField(Tag, blank=True, related_name='keywords')
image = models.ImageField(default='avatar.jpg', upload_to='images', blank=True, null=True)
def __str__(self):
return f'{self.profiler}'
Tag Serializer
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
Profile Serializer
class ProfileSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, read_only=True)
class Meta:
model = Profile
fields = ['id', # List All fields Exclude profiler => OneToOne field name
'bio', 'description',
'tags',
'image',
'birthDate', 'created', 'updated',
]
depth = 1
Profile Viewset
class ProfileViewSet(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
permission_classes = [IsAuthenticated]
def partial_update(self, request, *args, **kwargs):
data = request.data
profile_obj = Profile.objects.update(
profiler=self.request.user,
bio=data['bio'],
image=data['image'],
)
profile_obj.save()
for tag in data['tags']:
tag_obj = Tag.objects.update_or_create(
creator=self.request.user,
name=tag['name'], # name => Field Name in Tag Model
)
print(tag_obj)
profile_obj.tags.add(tag_obj) # tags => ManyToMany Field Name in Profile Model
serializer = ProfileSerializer(profile_obj)
return Response(serializer.data)
my aim is to create a new tag if this name is not exist, and also update profile tags
but my code is not working, and I don't know why
Can Any body help please ?
Finally I found the solution, But it still missing some steps
Profile Serializer
class ProfileSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True) # tags = ManyToMany Field Name
class Meta:
model = Profile
fields = ['id', # List All fields Exclude profiler => OneToOne field name
'bio', 'description',
'tags',
'image', 'get_image',
'birthDate', 'created', 'updated',
]
def update(self, instance, validated_data):
# Clear Existing Tags List Before Creating a New One By user
instance.tags.clear()
tags_data = validated_data.pop('tags')
instance = super(ProfileSerializer, self).update(instance, validated_data)
for tag_data in tags_data:
tag_qs = Tag.objects.filter(name__iexact=tag_data['name'])
if tag_qs.exists():
tag = tag_qs.first()
else:
tag = Tag.objects.create(**tag_data, creator=self.instance.profiler)
instance.tags.add(tag)
return instance
It Worked Like a charm but the problem is:
when I want to partial update of fields and i did't submit tags field,
It raises error
{
"tags": [
"This field is required."
]
}
Can some one help to keep my tags list as it is when the updated data missing tags field
Thanks in-advance

Django ManyToManyField Persistence Fails

I have a simple Django 3.1.0 app I need to create in order to assign Tasks with Tags (or assign tags into tasks).
My Model
class Task(models.Model):
user = models.CharField(max_length=33)
time = models.DateTimeField(auto_now_add=True)
task = models.CharField(max_length=500)
tags = models.ForeignKey('Tag', on_delete=models.SET_NULL, null=True)
class Tag(models.Model):
tag = models.CharField(max_length=30, default="No Tag")
members = models.ManyToManyField('Task')
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
My Form
class TaskForm(ModelForm):
class Meta:
model = Task
fields = ['user', 'task', 'tags']
template_name = 'tasks.html'
tags = ModelMultipleChoiceField(
queryset=Tag.objects.values().all(), widget=CheckboxSelectMultiple()
)
My View
def main(request):
model = Task.objects.values().all()
form = TaskForm()
con = {'context': list(model), 'form': form}
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
form.save_m2m()
return redirect('/')
else:
form = TaskForm()
return render(request, "tasks.html", con)
The migrations are successfull, and with the above code, the view shows a checkbox list with the fetched tags, but the problem is that when I hit Submit on the form, the values are not saved/written on the database but the page reloads successfully.
However, if I turn the following:
obj = form.save(commit=False)
form.save_m2m()
into
form.save(commit=True)
#form.save_m2m()
the values are written only from the fields 'user', 'task' - without the 'tags'
It's also funny that what fetches back on the webpage as values of the tags is in the shape of:
[checkbox] {'id': 1, 'tag': 'aks'}
What am I doing wrong? Thanks.
UPDATE after a comment below:
As Abdul Aziz suggested, I had to remove the values() from the queryset. But after that , to make it work, I had to add also:
In the model:
tag = models.CharField(max_length=100, default="No Tags")
and then refer to that one in the form and Vue template.
You have a ForeignKey set to the Tag model on your Task model, when you actually want a ManyToMany relationship between them. Remove the foreign key and set a related_name to the ManyToManyField in the Tag model like so:
class Task(models.Model):
user = models.CharField(max_length=33)
time = models.DateTimeField(auto_now_add=True)
task = models.CharField(max_length=500)
class Tag(models.Model):
tag = models.CharField(max_length=30, default="No Tag")
members = models.ManyToManyField('Task', related_name="tags")
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
Also in your form you have:
tags = ModelMultipleChoiceField(
queryset=Tag.objects.values().all(), widget=CheckboxSelectMultiple()
)
Why are you using values here? Remove it:
tags = ModelMultipleChoiceField(
queryset=Tag.objects.all(), widget=CheckboxSelectMultiple()
)

Django : Excluded fields are saved

I have a model :
from django.db import models
from tinymce.models import HTMLField
class Team(models.Model):
name = models.CharField(max_length=100, verbose_name='Team name')
city = models.CharField(max_length=100, verbose_name='Team city')
biography = HTMLField(verbose_name='Team biography')
country = models.ForeignKey('Country')
slug = models.SlugField(max_length=100)
def __str__(self):
return self.name
class Country(models.Model):
name = models.CharField(max_length=100, verbose_name='Country name')
code = models.CharField(max_length=5, verbose_name='Country code')
def __str__(self):
return self.code
And a form for this model:
from django import forms
from teams.models import Team
class TeamForm(forms.ModelForm):
class Meta:
model = Team
fields = (
'biography',
'city',
'country'
)
And this is my view:
def add(request):
if request.method == 'POST':
form = TeamForm(request.POST)
if form.is_valid():
send = True
form.save()
else:
form = TeamForm()
return render(request, 'teams/add.html', locals())
As you can see, all my model fields are required because I don't add argument 'null' to True in my model attributes.
In my ModelForm, for testing, I just specify fields biography, city and country.
But when I fill the form and send-it, data are saved in database, however is missing name and slug....
Why dont i have a django exception ?
Thanks for youre help
Neither of those fields are saved as Null, though. They are both character fields (SlugField is a subclass of CharField), and an empty charfield is saved as an empty string - which is perfectly valid from the database point of view.

Django Forms: MultipleSelect with choices from another model (Foreign Key)

I'm trying to create a form where the user can select multiple technician. When I add the line technician = forms.SelectMultiple(label='Technicians Involved') to my forms.py I get a big blank box with no data. How can I populate that box with the technicians from the User model?
models.py
class Incident(models.Model):
user_id = models.ForeignKey(User, related_name='user')
technician = models.ForeignKey(User, related_name='technician')
capa = models.CharField('capa number', max_length=9)
forms.py
class IncidentForm(forms.ModelForm):
###################### TRYING! ################################
technician = forms.SelectMultiple(label='Technicians Involved')
###############################################################
class Meta:
model = Incident
fields = [ 'user_id',
'technician',
'capa',
]
views.py
def report_incident(request):
template = "report.html"
if request.method == 'POST':
form = IncidentForm(request.POST)
if form.is_valid():
# Auto capturing logged in user
incident = form.save(False)
incident.user_id = request.user
incident.save()
return HttpResponseRedirect('/incidents/')
else:
form = IncidentForm() #an unbound form
return render(request, template, {'form': form})
************** UPDATE WITH CORRECTIONS I MADE BELOW *********************
models.py
class Incident(models.Model):
user_id = models.ForeignKey(User, related_name='user')
technician = models.ManyToManyField(User, related_name='technician')
capa = models.CharField('capa number', max_length=9)
forms.py
class IncidentForm(forms.ModelForm):
technician = forms.SelectMultiple()
class Meta:
model = Incident
fields = [ 'user_id',
'technician',
'capa',
]
views.py
No changes
admin.py
Changes made to view multiple technicians per incident in the admin interface.
class IncidentAdmin(admin.ModelAdmin):
list_display = ('id',
'user_id',
'capa',
'get_technicians'
)
def get_technicians(self):
return "\n".join([t.technicians for t in obj.technician.all()])
Try this out
class IncidentForm(forms.ModelForm):
technician = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), queryset=User.objects.all())
class Meta:
model = Incident
fields = [
'technician',
'capa',
]

Django Hidden Foreign Key in form using Meta model

I am working on a cookbook website using django and have run into a problem with a foreign key field in my form
the problem is that when i create my recipe i need to have a foreign key pointing to the cookbook that created this recipe but I don't want the user creating the recipe to see the original_cookbook field (they shouldn't have to)
I believe I need to use a widget (HiddenInput) but am I getting confused with the examples given on other sites. Also my friend mentioned something about setting an initial value in the original_cookbook view
tl;dr: I want to point the fk to the users cookbook while keeping the original_cookbook field hidden.
relevant code:
form:
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
model:
class Recipe(models.Model):
def __unicode__(self):
return self.name
original_cookbook = models.ForeignKey(Cookbook)
#cookbooks = models.ManyToManyField('Cookbook', related_name = 'recipes')
name = models.CharField(max_length=200)
author = models.CharField(max_length= 100)
picture = models.ImageField(upload_to = 'Downloads', blank=True)
pub_date = models.DateTimeField('date published', auto_now_add=True, blank=True)
ingredients = models.TextField()
steps = models.TextField()
prep_time = models.IntegerField()
TYPE_CHOICES= (
('SW', 'Sandwich'),
('AP', 'Appetizers'),
('SD', 'Sauces and Dressings'),
('SS', 'Soups and Salads'),
('VG', 'Vegetables'),
('RG', 'Rice, Grains and Beans'),
('PA', 'Pasta'),
('BR', 'Breakfast'),
('MT', 'Meat'),
('SF', 'Seafood'),
('BP', 'Bread and Pizza'),
('DT', 'Desserts'),
)
type = models.CharField(max_length = 2, choices=TYPE_CHOICES)
def index_queryset(self):
return self.objects.all()
view:
def createrecipe(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/index/')
else:
if request.method == 'POST':
form = RecipeForm(request.POST)
if form.is_valid():
recipe = form.save()
user = request.user
cookbooks = user.cookbooks
cookbook = cookbooks.all()[0]
cookbook.recipes.add(recipe)
return HttpResponseRedirect('/account')
else:
form = RecipeForm()
return render_to_response('cookbook/createrecipe.html',
{'form':form},
context_instance=RequestContext(request))
Add exclude = ('original_cookbook',) to your form's Meta class.
Then, in your if form.is_valid() code, do something like:
....
recipe = form.save(commit=False)
recipe.original_cookbook = whatever_that_is
recipe.save()
...
This is answered in the documentation.
from django import forms
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
widgets = {'cookbook': forms.HiddenInput