Django – Update Data



Django ORM uses the Active Record pattern for the interaction between a model class and its mapped database table. An instance of the model class corresponds to a single row in the table. Any of the attributes of the object results in updating the corresponding row.

In this chapter, we will focus on the different ways available in Django to update an already existing row in a relational database.

We shall use the Dreamreal model as given below for the exercise −

class Dreamreal(models.Model):
   website = models.CharField(max_length=50)
   mail = models.CharField(max_length=50)
   name = models.CharField(max_length=50)
   phonenumber = models.IntegerField()

   def __str__(self):
      return "Website: {} Email: {} Name: {} Ph.: {}".format(self.website, self.mail, self.name, self.phonenumber)

It is assumed that you have already performed the migrations and added a few objects in the model.

Update Object From Shell

Django has a useful feature with which you can invoke a Python shell inside the Django project’s environment. Use the shell command with the manage.py script −

python manage.py shell

In front of the Python prompt, import the Dreamreal model −

>>> from myapp.models import Dreamreal

The model.objects attribute returns the model Manager, and its all() method returns a QuerySet. We can limit the objects in the set by applying the filter.

To return the object with its primary key as 2, use the following statement −

obj = Dreamreal.objects.filter(pk = 2)

The model class has the get() instance method with which we can change the value of one or more attributes.

obj.update(f1=v1, f2=v2, . . .)

Let us update the name of the object with "pk = 2" −

obj.update(name='example')

The model manager also has a get() method that fetches a single instance corresponding to the given keyword argument −

obj = Dreamreal.objects.get(phonenumber = 2376970)

We can use a simple assignment to update an attribute. Let us change the phone number −

obj.phonenumber = 24642367570

To make the change persistent, you need to call the save() method

obj.save()

Perform Update Operation by Calling a View Function

Let us now perform the update operation by calling a view function. Define the update() function in views.py file. This function receives the primary key as the argument from its mapped URL.

from django.shortcuts import render
from django.http import HttpResponse
from myapp.models import Dreamreal

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk)
   obj.name="admin"
   obj.save()
   return HttpResponse("Update successful")

We also need to register this view in the urls.py file by adding a new path −

from django.urls import path
from . import views
from .views import DRCreateView, update

urlpatterns = [
   path("", views.index, name="index"),
   path("addnew/", views.addnew, name='addnew'),
   path("update/<int:pk>", views.update, name='update'),
]

Run the Django server and visit the URL http://localhost:8000/myapp/update/2. The browser emits the update success message.

Instead of using the hard-coded values as in the above example, we would like the data to be accepted from the user. We need to populate a HTML form with the object data corresponding to the primary key.

Modify the update() View Function

Modify the update() view function as shown −

from django.shortcuts import render
from django.http import HttpResponse
from myapp.models import Dreamreal

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk) 
   if request.method == "POST":
      ws = request.POST['website']
      mail = request.POST['mail']
      nm = request.POST['name']
      ph = request.POST['phonenumber']
      obj.name = nm
      obj.phonenumber = ph
      obj.save()
      return HttpResponse("<h2>Record updated Successfully</h2>")
   obj = Dreamreal.objects.get(pk=pk)
   context = {"obj":obj}
   return render(request, "myform.html", context)

We need to populate the form elements with the values of object attributes with the template variables.

Modify the myform.html script as follows −

<html>
<body>
   <form action="../update/{{ obj.pk }}" method="post">
      {% csrf_token %}
      <p><label for="website">WebSite: </label>
      <input id="website" type="text" value = {{ obj.website }} name="website" readonly></p>
      <p><label for="mail">Email: </label>
      <input id="mail" type="text" value = {{ obj.mail }} name="mail" readonly></p>
      <p><label for="name">Name: </label>
      <input id="name" type="text" value = {{ obj.name }} name="name"></p>
      <p><label for="phonenumber">Phone Number: </label>
      <input id="phonenumber" type="text" value = {{ obj.phonenumber }} name="phonenumber"></p>
      <input type="submit" value="Update">
   </form>
</body>
</html>

Visiting the URL http://localhost:8000/myapp/update/2 renders a HTML form pre-populated with the data belonging to pk=2. User can update the name and phonenumber fields.

Using ModelForm for Update

Next, we shall use the ModelForm class to render a HTML form with its input elements corresponding to the model field types. Let use the DereamrealForm class that inherits the Modelform

from django import forms
from .models import Dreamreal

class DreamrealForm(forms.ModelForm):
   class Meta:
      model = Dreamreal
      fields = "__all__"
        
      def __init__(self, *args, **kwargs):
         super(DreamrealForm, self).__init__(*args, **kwargs)
         self.fields['website'].widget = forms.TextInput(attrs={'readonly': 'readonly'})
         self.fields['mail'].widget = forms.TextInput(attrs={'readonly': 'readonly'})

Note − Here, we have set the readonly property of the website and mail fields in the class constructor.

The View function update() receives the primary key argument from the URL as before. When this function is called with POST method, the form data is used to update the existing object.

When the GET method is used, Django fetches the object corresponding to the primary key, and uses its attributes to populate the HTML form −

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk) 
   if request.method == "POST":
      form = DreamrealForm(request.POST)
      if form.is_valid():
         form.save()
         return HttpResponse("<h2>Record updated Successfully</h2>")
   obj = Dreamreal.objects.get(pk=pk)
   context = {"obj": DreamrealForm(instance=obj), "pk": obj.pk}
   return render(request, "myform.html", context)

Visit the http://localhost:8000/myapp/update/1 URL to display the HTML form with its fields filled with the record with pk=1. You can change the values and submit for the corresponding object to be updated.

Django Update Data

The UpdateView Class

Django defines a collection of generic view classes. The UpdateView class is specially designed for performing the INSERT query operation.

We define a subclass of UpdateView class and set its template_name property to myform.html that we have already created.

Add the following code in views.py file −

from django.views.generic.edit import UpdateView 
class DRUpdateView(UpdateView):  
   model = Dreamreal  
   fields = '__all__'  
   template_name = "myform.html"
   success_url = "../success/"

To register this view, we need to update the urls.py file for our app. Note that, to register a generic view, we use the as_view() method.

from django.urls import path
from . import views
from .views import DRCreateView, update, DRUpdateView

urlpatterns = [
   path("", views.index, name="index"),
   path("addnew/", views.addnew, name='addnew'),
   path("add/", DRCreateView.as_view(), name='add'),
   path("success/", views.success, name='success'),
   path("update/<int:pk>", views.update, name='update'),
   path("updateview/<int:pk>", views.update, name='update'),
]

We need not change the myform.html script, as it renders the HTML script based on the respective model.

Visit the updateview/1 URL to render the form pre-filled with the object having primary key = 1. Try and change one or more values and update the table.

Advertisements