How do I edit and delete data in Django? - python

I am using django 1.0 and I have created my models using the example in the Django book. I am able to perform the basic function of adding data; now I need a way of retrieving that data, loading it into a form (change_form?! or something), EDIT it and save it back to the DB. Secondly how do I DELETE the data that's in the DB? i.e. search, select and then delete!
Please show me an example of the code I need to write on my view.py and urls.py for perform this task.

Say you have a model Employee. To edit an entry with primary key emp_id you do:
emp = Employee.objects.get(pk = emp_id)
emp.name = 'Somename'
emp.save()
to delete it just do:
emp.delete()
so a full view would be:
def update(request, id):
emp = Employee.objects.get(pk = id)
#you can do this for as many fields as you like
#here I asume you had a form with input like <input type="text" name="name"/>
#so it's basically like that for all form fields
emp.name = request.POST.get('name')
emp.save()
return HttpResponse('updated')
def delete(request, id):
emp = Employee.objects.get(pk = id)
emp.delete()
return HttpResponse('deleted')
In urls.py you'd need two entries like this:
(r'^delete/(\d+)/$','myproject.myapp.views.delete'),
(r'^update/(\d+)/$','myproject.myapp.views.update'),
I suggest you take a look at the docs

To do either of these you need to use something called queries.
check link below for really great documentation on that!
(https://docs.djangoproject.com/en/2.2/topics/db/queries/)
To Delete Data:
b = ModelName.objects.get(id = 1)
b.delete()
This will delete the Object of the model w/ an ID of 1
To edit Data:
b = ModelName.objects.get(id = 1)
b.name = 'Henry'
b.save()
This will change the name of the Object of the model w/ an ID of 1 to be Henry

Read the following: The Django admin site. Then revise your question with specific details.

Related

Duplication of id values in another column in same table django

I am working on one python(django framework) project in which i have one user model which has 1000 users. I want to make one another column named priority id and need to put default id values in that priority id column accordingly (you can see it below).
id
username
email
priority_id
1
abc
abc#gmail.com
1
2
xyz
xyz#gmail.com
2
ofcourse i can do it manually using admin panel but for 1000 users it is time consuming.
how do i change models.py or admin.py or something else to achieve this?
def save(self, *args, **kwargs):
self.priority_id = self.id
return super().save(*args, **kwargs)
I don't know why you would ever want to do this, but you can achieve it by adding adding a BigAutoField to your user model. The field will then auto-increment the values for new users according to available ids.
In your models where you define the user, add following field.
priority_id = models.BigAutoField(null=False, unique=True)
well, i tried it using shell and it worked:
p = Users.objects.all()
for x in p:
profile = Users.objects.get(pk=x.id)
profile.priority_id= x.id
profile.save()
you can use this for me its working fine first you have to create with a default value and then use this function in views and just call once it will update the value as in id.
def update_value(request):
totaldata = modelsName.objects.all()
for j in totaldata:
modelsName.objects.filter(id=j.id).update(myid=j.id)
return HttpResponse('Success')

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)
...

Inline-like solution for Django Admin where Admin contains ForeignKey to other model

I have several Customers who book Appointments. Each Appointment has exactly one customer, though a customer can be booked for multiple appointments occurring at different times.
class Customer(model.Model):
def __unicode__(self):
return u'%s' % (self.name,)
name = models.CharField(max_length=30)
# and about ten other fields I'd like to see from the admin view.
class Appointment(models.Model):
datetime = models.DateTimeField()
customer = models.ForeignKey("Customer")
class Meta:
ordering = ('datetime',)
Now when an admin goes to browse through the schedule by looking at the Appointments (ordered by time) in the admin, sometimes they want to see information about the customer who has a certain appointment. Right now, they'd have to remember the customer's name, navigate from the Appointment to the Customer admin page, find the remembered Customer, and only then could browse their information.
Ideally something like an admin inline would be great. However, I can only seem to make a CustomerInline on the Appointment admin page if Customer had a ForeignKey("Appointment"). (Django specifically gives me an error saying Customer has no ForeignKey to Appointment). Does anyone know of a similar functionality, but when Appointment has a ForeignKey('Customer')?
Note: I simplified the models; the actual Customer field currently has about ~10 fields besides the name (some free text), so it would be impractical to put all the information in the __unicode__.
There is no easy way to do this with django. The inlines are designed to follow relationships backwards.
Potentially the best substitute would be to provide a link to the user object. In the list view this is pretty trivial:
Add a method to your appointment model like:
def customer_admin_link(self):
return 'Customer' % reverse('admin:app_label_customer_change %s') % self.id
customer_admin_link.allow_tags = True
customer_admin_link.short_description = 'Customer'
Then in your ModelAdmin add:
list_display = (..., 'customer_admin_link', ...)
Another solution to get exactly what you're looking for at the cost of being a bit more complex would be to define a custom admin template. If you do that you can basically do anything. Here is a guide I've used before to explain:
http://www.unessa.net/en/hoyci/2006/12/custom-admin-templates/
Basically copy the change form from the django source and add code to display the customer information.
Completing #John's answer from above - define what you would like to see on the your changelist:
return '%s' % (
reverse('admin:applabel_customer_change', (self.customer.id,)),
self.customer.name # add more stuff here
)
And to add this to the change form, see: Add custom html between two model fields in Django admin's change_form
In the ModelAdmin class for your Appointments, you should declare the following method:
class MySuperModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if obj:
# create your own model admin instance here, because you will have the Customer's
# id so you know which instance to fetch
# something like the following
inline_instance = MyModelAdminInline(self.model, self.admin_site)
self.inline_instances = [inline_instance]
return super(MySuperModelAdmin, self).get_form(request, obj, **kwargs)
For more information, browser the source for that function to give you an idea of what you will have access to.
https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L423
There is a library you can use it.
https://github.com/daniyalzade/django_reverse_admin
But if you want to use link to object in showing table you can like this code:
def customer_link(self, obj):
if obj.customer:
reverse_link = 'admin:%s_%s_change' % (
obj.customer._meta.app_label, obj.customer._meta.model_name)
link = reverse(reverse_link, args=[obj.customer.id])
return format_html('More detail' % link)
return format_html('<span >-</span>')
customer_link.allow_tags = True
customer_link.short_description = 'Customer Info'
And in list_display:
list_display = (...,customer_link,...)

Using FormWizard and saving the forms data in between before the completion of the whole process?

I am using FormWizard to complete a set of operation in my app, I have two models Employee and Person, Employee class inherits Person, and all the fields of Person are available for Employee object.
Now I am creating a set of forms using FormWizard, I just wanted to know that. If a user starts entering the data in the forms and fills upto 2 forms out of 4 and is willing to fill the rest of the forms afterwards. So is this possible that the data for the two forms which he filled can be saved in the database.
And the next time he comes can complete the operation form the 3rd form.
If anyone knows that then plz help me out, it would be a great help. Thank You!
what you can do is every step, save out the form state to some serialised object in db ForeignKeyed to the user.
then when hooking up the formwizard, wrap the formwizard view in a custom view which checks if the user has a saved form and if so deserialises and redirects to the appropriate step.
Edit: seems formwizard saves state in POST. only need to save postdata.
models.py:
class SavedForm(Model):
user = ForeignKey(User)
postdata = TextField()
views.py:
import pickle
class MyWizard(FormWizard):
def done(self, request, form_list):
SavedForm.objects.get(user=request.user).delete() # clear state!!
return render_to_response('done.html',)
formwizard = MyWizard([Form1, Form2]) <- class name, not instance name
def formwizard_proxy(request, step):
if not request.POST: #if first visit, get stored data
try:
prev_data = SavedForm.objects.get(user=request.user)
request.POST = pickle.loads(prev_data.postdata)
except:
pass
else: # otherwise save statet:
try:
data = SavedForm.objects.get(user=request.user)
except:
data = SavedForm(user=request.user)
data.postdata=pickle.dumps(request.POST)
data.save()
return formwizard(request)
edit: changed formwizard constructor

How to validate django form only when adding not editing

How could we make the django form to not validate if we are editing, not adding a new record. The code as following :
class PageForm(forms.Form):
name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'class':'textInput'}))
description = forms.CharField(max_length=300, required=False,widget=forms.TextInput(attrs={'class':'textInput'}))
body = forms.CharField(widget=forms.Textarea)
template = forms.CharField(max_length=30,widget=forms.TextInput(attrs={'class':'textInput'}))
navbar = forms.BooleanField(required=False, widget=forms.Select(choices=(('True','True'),
('False', 'False'))))
publish = forms.BooleanField(widget=forms.Select(choices=(('Published','Publish Now'),
('Private','Private'),
('Draft','Draft'))))
def save(self, page=None, commit=True):
data = self.cleaned_data
if not page:
page = models.Page(key_name=data['name'].replace(' ','-'))
page.name = data['name']
page.description = data['description']
page.body = data['body']
page.template = data['template']
page.publish = data['publish']
if commit: page.put()
return page
# prevent the same page 's name
def clean_name(self):
name = self.cleaned_data['name']
query = models.Page.all(keys_only=True)
query.filter('name = ', name)
page = query.get()
if page:
raise forms.ValidationError('Page name "%s" was already used before' % name)
return name
The purpose of this name validation is to prevent the records with the same name. BUt i found that, it also validate on edit, so we couldn't edit records, since it will said 'records with same name already exist'.
Actually for editing, the page param on save function wont be none, but prev record instead, and wil be none on saving a new one. But how we read this param, on clean_name function so we can now whether it is editing or creating?
Thanks a lot!
in your clean method, you can use self.initial to know whether it is adding or editing. If it is editing, the self.initial will not be empty. But when it is adding, self.initial will be dictionary of what the previous value.
If you are editing form, then the form has some instance, and you can check if that exists.
If it does, then you are probably editing existing object.. right?
Example:
If you are editing object with form, you create form object much like this:
form = MyForm(instance = myobject)
Then in your form class methods you can check if form has saved instance in a way that it is described here:
Test if Django ModelForm has instance
in your clean_name function exclude the current object from queryset
query.filter('name = ', name).exclude(pk=self.pk)
or change the if condition to check that page and current object are not the same.
Sorry, I couldn't comment below your guys post, don't know why.
#sunn0 : I didn't use django models, coz deploy the app in appengine, so use appengine model instead.
#Zayatzz : May you show a little code how to do it? Since whether we are adding or editing, we always bound the form to request.POST before validation, so don't know how to differentiate.
#Ashok : I made a workaround based on your suggestion. Since previously I didn't pass the pk to form, but passing the prev object as param instead, so couldn't exclude by using pk. So, I change the code and put additional key as pk (if create, let key empty, but if edit fill key with pk) and just check in if condition, if key field not empty, then it means we are editing. Not sure if it is best practice, but it works anyway.
I can suggest to override form's init method
https://stackoverflow.com/a/70845558/15080117
because there is an argument instance.

Categories

Resources