How to get object uid from previous page in Django web-app? - django

I`m trying to make a CreateView form that takes the UID of the object as a foreign key from the previous page.
Here I got DetailView of Plan model:
class PlanDetailView(IsStaffPermissionMixin, DetailView):
model = Plan
template_name = "backoffice/plans/plan_detail.html"
context_object_name = 'plan'
def get_object(self):
uid = self.kwargs.get("uid")
return get_object_or_404(Plan, uid=uid)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
practice_sessions = PracticeSession.objects.all().filter(plan__uid=self.kwargs.get("uid"))
context['practice_sessions'] = practice_sessions
return context
And here I got a PracticeSession CreateView:
class PracticeSessionCreateView(IsStaffPermissionMixin, CreateView):
model = PracticeSession
template_name = "backoffice/practice_session/practice_session_create.html"
fields = ['uid', 'title', 'plan', 'snippet', 'welcome_content', 'done_content', 'order_index', ]
success_url = reverse_lazy('practice-sessions')
As you understand, PracticalSession contains Foreign Key for the Plan model
Now I want that when I click on the button to create a PracticalSession (the picture below), I create a form in which the plan field already contains a "uid" of Plan from the page of which I create a new PracticalSession
My Form:
class PracticeSessionCreateForm(ModelForm):
class Meta:
model = PracticeSession
fields = '__all__'
Big THANK YOU In advance !!!

Related

How to save multiple models with multiple modelForms in one django form-tools WizardView

Here's my scenario:
I have two models:
class Person(models.Model):
# --- model fields ---
class Qualification(models.Model):
owner = models.ForeignKey(Person, on_delete=models.CASCADE)
# --- other fields ---
And Model forms:
class PersonalForm(forms.ModelForm):
class Meta:
model = Person
fields = ['first_name', 'last_name', 'email', 'id_number', 'date_of_birth']
class IsQualifiedForm(forms.ModelForm):
class Meta:
model = Person
fields = ['is_qualified']
class QualificationForm(forms.ModelForm):
class Meta:
model = Qualification
fields = ['level', 'course_name', 'attainment']
And finally my wizard view:
class Wizard(SessionWizardView):
template_name = 'demo/wizard_test.html'
form_list = [
("personal", PersonalForm),
("is_qualified", IsQualifiedForm),
("qualifications", QualificationForm),
]
def get_form_instance(self, step):
return self.instance_dict.get(step, None)
def done(self, form_list, **kwargs):
# What is the exact logic to be applied here to save the model forms concurrently?
return redirect('home')
I'm trying to save the form but I run into errors:
When I try to call:
for form in form_list:
form.save()
in the done() method, I get an error because the is_qualified is intercepted as null in the first step.
Plus, how do I get to set the owner field's value to the currently created person?
Any help would be appreciated.
If is_qualified is not nullable in your Person model, validation will always fail. What you can do is save both PersonalForm and IsQualifiedForm in one go, since they refer to the same model anyways. To do this, set the values of one form in the other. For example:
def done(self, form_list, **kwargs):
person = form_list[0].save(commit=False)
person.is_qualified = form_list[1].cleaned_data['is_qualified']
person.save()
return redirect('home')
Some notes:
You should probably use named steps instead of relying on form index
If your case is as simple as the form you provided, you should just make the first two forms a single form

django fill form field automatically from context data

I have a form attached to a DetailedView and its working fine when saved. I would like the form field(position) to be prepopulated with the value coming from the slug of the detailed view(e.g jobs/human-resource-manager). The Model of the form field has a Foreignkey to the JobPost model. Need help. Part of my view looks like this
class JobsDetailView(DetailView):
model = JobPost
template_name = 'job_post-detail.html'
def get_context_data(self, **kwargs):
context = super(JobsDetailView, self).get_context_data(**kwargs)
context['position'] = JobPost.objects.order_by('position')
context['job_app_form'] = JobsForm()
return context
foms.py
from django import forms
from job_post.models import JobsApplied
class JobsForm(forms.ModelForm):
class Meta:
model = JobsApplied
fields = '__all__'
def form_valid(self, form):
form.instance.customuser = self.request.user
return super().form_valid(form)
I'm assuming you do not want your users to be able to interact with or change these prefilled values.
I'm making a comments/review model and I want it to automatically link reviews to the people they are about
models.py
class Review(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
...
I hide the person field in the ReviewsForm to prevent user input by either omitting it from the 'fields' or adding it to an 'exclude'.
forms.py
class ReviewsForm(forms.ModelForm):
class Meta:
model = Review
fields = ('rating', 'summary', 'review_text')
Then, when processing the form in the view, I use commit=False so I can manipulate field values before saving to the database.
Include prefilled values, save and then redirect the user wherever is ideal
views.py
def person(request, area_slug, category_slug, person_id):
...
if form.is_valid():
pending_review = form.save(commit=False)
pending_review.person = Person.objects.get(pk = person_id)
pending_review.save()
return HttpResponseRedirect(...)
django fill form field automatically from context data for django form and django formsets
For formsets in forms.py
StoreRequestAccessoryUpdateFormSet = forms.modelformset_factory(StoreRequestAccessory, form=StoreRequestAccessoryUpdateForm, exclude=["storeRequestId"], can_delete=True)
In get_context_data you can add it as you like for django
class StoreRequestUpdateView(LoginRequiredMixin, UpdateView):
template_name = "Inventory/Stock/StoreRequest/StoreRequestUpdateView.html"
model = StoreRequest
fields = ["fromStoreId", "toStoreId", "reference", "status", "remark"]
def get_context_data(self, **kwargs):
context = super(StoreRequestUpdateView, self).get_context_data(**kwargs)
print(self.object.pk)
context.update({
# "StoreRequestForm": context.get("form"),
"StoreRequestForm": StoreRequestUpdateForm(instance=StoreRequest.objects.get(id=self.object.pk)),
"StoreRequestAccessoryForm": StoreRequestAccessoryUpdateFormSet(
queryset=StoreRequestAccessory.objects.filter(storeRequestId=self.object.pk),
prefix="storereq_accessory_form"),
})
return context

Rendering user specific data

I'm trying to create a webapp which renders data for the user specifically.
I have to models, one for the user (djangos built in User) and one for the data to be rendered.
My model ffor the user:
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
def __str__(self):
return self.user.username
My model for the data:
class MyModel(models.Model):
user_k = models.ForeignKey(User,related_name='RelatedName',on_delete=models.CASCADE)
Date_Time = models.DateTimeField(default=timezone.now)
DataOne = models.PositiveIntegerField(null=True)
DataTwo = models.PositiveIntegerField(null=True)
DataThree = models.PositiveIntegerField(null=True)
In my views.py file i have this view for it:
class MyView(DetailView):
model = models.User
context_object_name = 'mylist'
template_name = 'my_app/example.html'
def get_queryset(self):
return User.objects.filter(user_k=self.request.user)
And my problem that i can't solve is that I'm getting this error:
Cannot query "user": Must be "MyModel" instance.
I've googled it multiple times also tried the django documentation.
My guess is that the problem might be in the my models, where my intention was to connect my second model to the username, but I'm not sure.
Thanks for your help!
There is no reason User would have a user_k attribute so User.objects.filter(user_k=xxx) makes no sense.
Either use your MyModel model:
class MyView(DetailView):
model = models.MyModel
def get_queryset(self):
return MyModel.objects.filter(user_k=self.request.user)
Or use your UserProfileInfo model:
class MyView(DetailView):
model = models.UserProfileInfo
def get_queryset(self):
return UserProfileInfo.objects.filter(user=self.request.user)

Adding an object to a specific foreign key using CreateView django

From my views:
class SongCreate(CreateView):
model = Song
fields = ['album', 'name']
My functionality of adding a song (this) to an album is inside the details template of an album A. However, I want the input only be the name and not the album anymore since the song's album should automatically be "A." How do I make the code above behave such?
From my urls:
url(r'album/(?P<pk>[0-9]+)/song/add/$', views.SongCreate.as_view(), name='song-add')
You can use the get_initial method:
class SongCreate(CreateView):
model = Song
fields = ['album', 'name']
def get_initial(self):
return {
'album': Album.objects.get(id=self.kwargs.get('pk')),
}
Or you can use the form_valid method:
class SongCreate(CreateView):
model = Song
fields = ['name']
def form_valid(self, form):
form.instance.album = Album.objects.get(id=self.kwargs.get('pk'))
return super(SongCreate, self).form_valid(form)

what does the autocomplete-light return?

I have recently installed autocomplete-light in my app.
Autocomplete filters through the field called 'name' in a table called institution. However, what is post through the view is the 'id' of the same object, not the name.
Does anyone know why that is?
My view is:
class UserAccountsUpdate(UpdateView):
context_object_name = 'variable_used_in `add_user_accounts.html`'
form_class = AddUserAccountsForm
template_name = 'add_user_accounts.html'
success_url = 'add_user_accounts.html'
def add_user_institution_details(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = AddUserAccountsForm(request.POST)
# check whether it's valid:
if form.is_valid():
institution_selected = Institution.objects.get(id=name)
form.save()
return render(request)
#get object
def get_object(self, queryset=None):
return self.request.user
The form is:
class AddUserAccountsForm(forms.ModelForm):
name = forms.ModelChoiceField(required=True, queryset=Institution.objects.all(), widget=autocomplete_light.ChoiceWidget('InstitutionAutocomplete'), label="")
class Meta:
model = Institution
fields = ('name',)
autocomplete-light's ChoiceWidget uses the Model's PrimaryKey for post requests by default, which in your case is id.
Since you did not post your models.py I can only assume that name is a CharField in the Institution model and you are just using autocomplete here to simplify the adding of a name.
To realize this use TextWidget and forms.CharField:
class AddUserAccountsForm(forms.ModelForm):
name = forms.CharField(
required=True,
widget=autocomplete_light.TextWidget('InstitutionAutocomplete'),
label="",
)
class Meta:
model = Institution
fields = ('name',)