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

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',
]

Related

Add extra value before save serializer

My form sends data to django-rest-framework, but the form contains two fields, and I want to save 5 fields in the database, other fields I calculate on my own (they are not sent by the form). How can I add additional values before saving?
so, form send 'user' and 'comment' values, I want add 'article', 'ip_address' before save to DB
models.py
class Comments(models.Model):
article = models.ForeignKey(Articles, on_delete=models.CASCADE)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
comment = models.TextField(verbose_name=_('Comment'))
submit_date = models.DateTimeField(_('Created'), auto_now_add=True)
ip_address = models.CharField(_('IP address'), max_length=50)
is_public = models.BooleanField(verbose_name=_('Publish'), default=False)
serializers.py
class CommentsSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.first_name')
class Meta:
model = Comments
fields = ('user', 'comment')
views.py
class AddCommentViewSet(viewsets.ModelViewSet):
queryset = Comments.objects.all()
serializer_class = CommentsSerializer
You have to override create() method:
class CommentsSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.first_name')
class Meta:
model = Comments
fields = ('user', 'comment')
def create(self, validated_data):
new_comment = models.Comment()
new_comment.user = validated_data['user']
new_comment.comment = validated_data['comment']
new_comment.article = get_your_article_somehow()
new_comment.ip_address = get_your_ip_address_somehow()
new_comment.save()
return new_comment

setting instance for forms in UpdateView

i have an UpdateView with a couple of forms and i'm trying to understand how to set the instance for the other form because the first form work just fine but the second form is always empty and i cant figure out how to set the instance for that modelform .
class ProfileUpdateView(UpdateView):
# model = User
queryset = User.objects.all()
form_class = UserForm
second_form_class = ClientForm
template_name = 'accounts/update.html'
def get_object(self):
user = get_object_or_404(User , username__iexact=self.kwargs.get('username'))
return user
def get_context_data(self, **kwargs):
user = self.object
profile = Client.objects.get(id = user.clients.id)
context = super(ProfileUpdateView, self).get_context_data(**kwargs)
if user.is_client and 'ClientForm' not in context:
context['client_form'] = self.second_form_class(self.request.GET, instance=profile )
return context
models
class User(AbstractUser):
gender_choice =(
('Male','Male'),
('Female','Female'),
)
is_artisan = models.BooleanField('artisan status', default=False)
is_client = models.BooleanField('client status', default=False)
avatar = models.ImageField(null=True ,blank=True)
birth_day = models.DateField(null=True,blank=True)
birth_location = models.CharField(max_length=30, null=True ,blank=True)
adresse = models.CharField(max_length=30, null=True ,blank=True)
gender = models.CharField(max_length=6,choices=gender_choice,)
phone = models.CharField(max_length=10 ,null=True ,blank=True)
class Client(models.Model):
client_choice = (
('erson','person'),
('company','company'),
)
client_type = models.CharField(max_length=10,choices=client_choice,)
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, related_name='clients')
forms
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email','avatar','adresse','birth_location','birth_day' ,'gender' ,'phone')
class ClientForm(forms.ModelForm):
class Meta:
model = Client
fields = ('client_type',)
the question now how/where can i set the instance for the second form and where is the first form instance is set .
Is that a typo in get_context_data? Should it be:
if user.is_client and 'client_form' not in context:
context['client_form'] = self.second_form_class(self.request.GET, instance=profile)
The first form is set in UpdateView's super class FormMixin.get_context_data (which in turn calls FormMixin.get_form()). Docs for FormMixin

Django add recipe form

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.

Current user as a comment's autor (DJANGO)

I have create a model called 'Comentario' where the logged user can create his own comment. How can I do to automatically save as the author of the comment the logged user. Here I show my schema:
models.py
class Comentario (models.Model):
titulo = models.CharField(max_length=50)
texto = models.CharField(max_length=200)
autor = models.ForeignKey (Perfil, editable=False, blank=True)
fecha_publicacion = models.DateTimeField(auto_now_add=True)
tag = models.ManyToManyField(Tags, blank=True)
def __str__(self):
return (self.titulo)
views.py
class ComentarioCreate (LoginRequiredMixin,CreateView):
model = Comentario
form_class = ComentarioForm
template_name = 'home/comentario_form.html'
success_url = reverse_lazy ('home:listar')
def save(self):
autor=self.request.user.username
user.save()
forms.py
class ComentarioForm(forms.ModelForm):
class Meta:
model = Comentario
fields = [
'titulo',
'texto',
'tag',
]
labels = {
'titulo': 'Titulo',
'texto' : 'Descripcion',
'tag' : 'Etiquetas',
}
widgets = {
'titulo':forms.TextInput(attrs={'class':'form-control'}),
'texto':forms.TextInput(attrs={'class':'form-control'}),
'tag':forms.CheckboxSelectMultiple(),
}
Perfil is a model which inherits form AbstractUser.
models.py
class Perfil(AbstractUser):
nom_puesto = models.ForeignKey(Puesto, blank = True)
def __str__(self):
return '{}'.format(self.username)
How can I do to have in the field 'autor' the username of the logged user?
thank you for your answer!
The method to override is form_valid, not save; see models and request.user which explains exactly what to do.

BaseInlineFormSet clean method in admin false trigger?

I am trying to update a field in Admin but it raises Validation Error from clean method which I have defined as follows in forms.py:
class BasePhoneFormSet(BaseInlineFormSet):
def clean(self):
super(BasePhoneFormSet, self).clean()
if any(self.errors):
return
phone_numbers = []
for form in self.forms:
if form.cleaned_data.get('number') in phone_numbers:
raise forms.ValidationError(
'Duplicate Entry')
phone_numbers.append(form.cleaned_data.get('number'))
PhoneFormSet = inlineformset_factory(
Post,
Phone,
formset=BasePhoneFormSet,
form=PostForm,
fields = ('number',),
can_delete=False, # admin still shows delete next to the phone number
extra=0,
validate_min=True,
min_num=1,
)
This code works in the views , but in the admin, I can't update or add any phone number since it raises the same ValidationError for duplicate entry.
here is my models.py
class Post(TimeStampedModel, models.Model):
unique_id = models.CharField(max_length=6, unique=True)
user = models.ForeignKey(User, related_name='posts')
city = models.ForeignKey(City, related_name='posts')
class Phone(TimeStampedModel, models.Model):
number = models.CharField(
validators=[phone_regex], max_length=15)
post = models.ForeignKey(Post)
And this is admin.py
class PhoneInline(admin.StackedInline):
model = Phone
formset = PhoneFormSet
class PostAdmin(admin.ModelAdmin):
inlines = [
PhoneInline,
]
I looked into BaseInlineFormSet in models.forms but I got confused more.
class PhoneInline(admin.StackedInline):
model = Phone
formset = BasePhoneFormSet
fields = ('number',)
can_delete = False
extra = 0
min_num = 1