Created related objects using django createview - python

Hey All I am using Django 1.10.7
I am creating a form that creates a store location to a store. Now what I want to happen is to have the store already associated with the store location when the form is loaded.
The url has the proper id of the foreign key of the store ex: localhost:8000//office/dealer/1/location/create. and I see that that the store key is in the request keyword arguments. But I can't get how to associate that into the form. Any help would be really appreciated
Here is how I have my code
#views.py
class DealerLocationCreateView(CreateView):
model = models.DealerLocation
fields = ['dealer'
'dealer_location_name',
'dealer_location_mailing_address',
'dealer_location_mailing_city',
'dealer_location_mailing_state',
'dealer_location_mailing_zipcode',
'dealer_location_mailing_phone',
'dealer_location_shipping_address',
'dealer_location_shipping_city',
'dealer_location_shipping_state',
'dealer_location_shipping_zipcode',
'dealer_location_shipping_phone'
]
def form_valid(self, form):
form.instance.dealer = self.request.dealer_pk
return super(DealerLocationCreateView, self).form_valid(form)
-
# urls.py
url(r'^dealer/(?P<dealer_pk>\d+)/location/create', DealerLocationCreateView.as_view(), name='new-location'),

Why not using :
def form_valid(self, form):
pk = self.kwargs.get("dealer_pk", None)
form.instance.dealer = pk
return super(DealerLocationCreateView, self).form_valid(form)

Related

Django CreateView success url with pk from different unrelated model

I have a django CreateView where users can create new words. I also have an unrelated Song model, where users can choose to add words from the lyrics of the songs. So I've created a separate CreateView for this, so that I can have a different success url. The success url should go back to the song where the user was browsing. But I am struggling to figure out how to pass the pk of this particular object to the CreateView of a different model.
This is my special CreateView:
class CreateWordFromSong(LoginRequiredMixin, generic.CreateView):
template_name = 'vocab/add_custom_initial.html'
fields = ("target_word","source_word", etc.)
model = models.Word
from videos.models import Song
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super(CreateWordFromSong, self).form_valid(form)
success_url = reverse_lazy('videos:song-vocab', kwargs={'pk': song_pk) #how to get song_pk?
Everything works when I replace song_pk with the actual pk.
I overwrite form_valid so that the user can be saved with the new object. Perhaps there is a way I can alter this so that I can also get the song_pk? I've played around with it a bit, but without luck.
I get the song_pk from my url:
path('song/<int:song_pk>/', views.CreateWordFromSong.as_view(), name='create-song'),
So I should have access to it. But when I try adding it to my view:
class CreateWordFromSong(LoginRequiredMixin, generic.CreateView, song_pk)
I get the error: name 'song_pk' is not defined.
You could add in class CreateWordFromSong instead success_url method get_success_url
def get_success_url(self):
return reverse_lazy('videos:song-vocab', kwargs={'pk': self.kwargs.get('song_pk')})
It will be work, if action in template with form be like this
<form action="{% url 'create-song' song_pk=song.pk %}" method="post">
(Surely a bit lately ...)
I faced a similar case but not sur this matches with your.
I have a list of Mapping objects (children) related to Flow object (parent and ForeignKey).
This list uses the Flow PK.
urls.py
path('flow/<int:pk>/mapping',
mappingColumnOneFlowListView.as_view(), name='mapping-details'),
On each line of Mapping objects, I got a "delete" button.
After deletion, I want to lead back to the list of the Flow Mapping but couldn't because the PK used in the view lead to the (deleted) Mapping.
Another solution would have consisted in leading to another URL without pk (eg. absolute_url in Model) but this was not what I wanted.
It's surely not the best way to achieve the goal but I found this:
in my DeleteView i added :
def get_success_url(self):
pk = self.kwargs['pk'] # Mapping's PK
flow_pk = MappingField.objects.filter(
pk=pk).first().fl_id.pk # fl_id.pk = Flow's PK (FK)
return reverse('mapping-details', kwargs={'pk': flow_pk})

Django Class Based View UpdateView Restricted User

I am trying to use a Django UpdateView to display an update form for the user. https://docs.djangoproject.com/en/1.8/ref/class-based-views/generic-editing/
I only want the user to be able to edit their own form.
How can I filter or restrict the the objects in the model to only show objects belonging to the authenticated user?
When the user only has one object I can use this:
def get_object(self, queryset=None):
return self.request.user.profile.researcher
However, I now need the user to be able to edit multiple objects.
UPDATE:
class ExperimentList(ListView):
model = Experiment
template_name = 'part_finder/experiment_list.html'
def get_queryset(self):
self.researcher = get_object_or_404(Researcher, id=self.args[0])
return Experiment.objects.filter(researcher=self.researcher)
class ExperimentUpdate(UpdateView):
model = Experiment
template_name = 'part_finder/experiment_update.html'
success_url='/part_finder/'
fields = ['name','short_description','long_description','duration', 'city','address', 'url']
def get_queryset(self):
qs = super(ExperimentUpdate, self).get_queryset()
return qs.filter(researcher=self.request.user.profile.researcher)
URL:
url(r'^experiment/update/(?P<pk>[\w\-]+)/$', login_required(ExperimentUpdate.as_view()), name='update_experiment'),
UpdateView is only for one object; you'd need to implement a ListView that is filtered for objects belonging to that user, and then provide edit links appropriately.
To prevent someone from simply putting the URL for an edit view explicitly, you can override get_object (as you are doing in your question) and return an appropriate response.
I have successfully been able to generate the list view and can get
the update view to work by passing a PK. However, when trying to
override the UpdateView get_object, I'm still running into problems.
Simply override the get_queryset method:
def get_queryset(self):
qs = super(ExperimentUpdate, self).get_queryset()
# replace this with whatever makes sense for your application
return qs.filter(user=self.request.user)
If you do the above, then you don't need to override get_object.
The other (more complicated) option is to use custom form classes in your UpdateView; one for each of the objects - or simply use a normal method-based-view with multiple objects.
As the previous answer has indicated, act on the list to show only the elements belonging to the user.
Then in the update view you can limit the queryset which is used to pick the object by overriding
def get_queryset(self):
qs = super(YourUpdateView, self).get_queryset()
return qs.filter(user=self.request.user)

How to render an html template with data from view?

I am new to django. I made a form. I want that if the form is filled successfully then django should redirect to a success page showing the name entered in the form but no parameters should be present in the url itself.
I searched on the internet and the solution I got was to redirect to url with pk as a get parameter which fetches the data and shows in the view. But I don't want to pass any thing in the url itself. and some websites say that http can't redirect with post data.
Here's my views.py
class UserRegistrationView(CreateView):
model = UserForm
template_name = 'userregistration.html'
form_class = UserForm
success_url = 'success'
def get_success_url(self):
return reverse('success',kwargs = {'name' : self.object.firstName})
and here's the template to which I want to redirect:
<h2>Congratualations for registering {{name}} </h2>
Basically what I want is that if the person fill form mentioning his/her firstName as "xyz" then the redirected success page should say that "Congratulations for registering xyz"
You can use django sessions, which I believe installed by default in 1.8
Look here
# Set a session value:
request.session["fav_color"] = "blue"
# Get a session value -- this could be called in a different view,
# or many requests later (or both):
fav_color = request.session["fav_color"]
# Clear an item from the session:
del request.session["fav_color"]
You can pass your pk via session and extract your object in another view without affecting your url.
Make sure you clean up after yourself.
Let me know if more help needed.
One of the possible ways of passing data between views is via sessions. So, in your UserRegistrationView you need to override the form_valid method as shown below.
class UserRegsitrationView(CreateView):
def form_valid(self,form):
self.request.session['name'] = self.object.firstName
return super(UserRegistrationView,self).form_valid(form)
class SuccessView(TemplateView):
template_name = "success_template.html"
def get_context_data(self,**kwargs):
context = super(SuccessView,self).get_context_data(**kwargs)
context['name'] = self.request.session.get('name')
del self.request.session['name']
return context
One more thing that you can modify in your code is that you need not declare success_url if you are overriding get_success_url

Updating foreign key field in Django

I have a form that displays a drop down for a foreignkey field. The form saves the users selection, however I want the view to update the database entry rather than inserting a new one. Whats the best way to go about this?
Current function:
def formset_valid(self, formset):
self.object = formset.save()
self.object.save()
return HttpResponseRedirect(self.get_success_url())
I have tried something like this:
d = RevisionDefaultType.objects.get(id=1)
n = RevisionSettings.objects.get(self.object)
d.defaultrevisiontype = n
d.save()
But it throws an error that the data being updated is not an instance.
I managed to tweak the update example from https://docs.djangoproject.com/en/dev/topics/db/queries/#saving-foreignkey-and-manytomanyfield-fields. This seems to be working as desired.
def formset_valid(self, formset):
self.object = formset.save(commit=False)
revdefault = RevisionDefaultType.objects.get(pk=1)
revget = RevisionSettings.objects.get(global_revision_type=self.object)
revdefault.defaultrevisiontype = revget
revdefault.save()
return HttpResponseRedirect(self.get_success_url())
Thanks again for the help.
You must add force_update=True to your save() function.
For more info about How Django knows to UPDATE vs. INSERT see this link in django's documentation.

How to use Django AutoField to edit a modelForm?

The Django doc mention that a Model AutoField will not be represented in a form built with a ModelForm.
When editing and saving that form, how should I supposed to know the underlying AutoField id value to save correctly my form data to database?
I know I can inject myself in the edit form an hidden field to know which row has been edited but is there a way Django manage that hidden field or some other mecanism automatically?
Thanks a lot
Etienne
You do that by specifying the instance=<> parameter when you are using ModelForm.
More on this in the documentation here
Example usage of a create/update view:
def myview(request, id=None):
if id:
obj_to_edit = MyModel.objects.get(id=1)
form = MyForm(instance=obj_to_edit)
else:
obj_to_edit = None
form = MyForm()
if request.method == 'POST':
if id: #update
form = MyForm(request.POST, instance=obj_to_edit)
else: #create
form = MyForm(request.POST)
#rest of the code
and the URL would have something like:
url(r'/blah/create/', 'myview'),
url(r'/blah/edit/(?P<id>[\d+])/', 'myview')
Now, django understands that it needs to edit rather than create new objects.
Also note that if you are using forms.Form, you would have to manually query for the unique fields, or inject the hidden id field as you have mentioned.
Usually when you're editing a form the specific instance that you want to edit will be identified in your URL using either the primary key or a slug field, e.g:
www.example.com/model/edit/6/
or
www.example.com/model/edit/object_slug/
You would then set up your urls.py to pass that parameter to your view, where you would use the example provided by karthkir (I'll use the primary as the example from here)
urls.py
urlpatterns = patterns('',
url(regex=r'^model/edit/(?P<pk>\d+)/$', 'myapp.views.myview', name='add_customer'),
)
views.py
def myview(request, pk):
obj_to_edit = MyModel.objects.get(id=pk)
...

Categories

Resources