I am trying to build a Django (version 3.05) REST API call that will render to a chosen HTML template.
I am, however, receiving a number of errors that I haven't found a solution to on StackOverflow (And yes, I've looked far and wide).
Since my errors are many and varying depending on what I attempt, let me rather ask how to do it correctly to begin with.
In my view set up (below), what do I need to add (or change) in order to render the queryset to an HTML template?
models.py:
from django.db import models
class Hero(models.Model):
name = models.CharField(max_length=60)
alias = models.CharField(max_length=60)
def __str__(self):
return self.name
serializers.py:
from rest_framework import serializers
from .models import Hero
class HeroSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Hero
fields = ('name', 'alias')
views.py:
from rest_framework import viewsets
from .serializers import HeroSerializer
from .models import Hero
class HeroViewSet(viewsets.ModelViewSet):
queryset = Hero.objects.all().order_by('name')
serializer_class = HeroSerializer
# over here - how do I render the queryset /to/my/template.html
myapi/urls.py:
from django.urls import include, path
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'heroes', views.HeroViewSet)
you should change your view from ModelViewSet to APIView.
with API view you can include renderer_classes and template_name.
check here for more information
Related
I am trying to accomplish the following workflow in my Django project:
Query my database
Convert the returned queryset to a pandas dataframe in order to perform some calculations & filtering
Pass the final dataframe to Django REST API Framework
if I understand correctly, I have to use django-pandas for Step 2. and Django REST Pandas for Step 3.
I installed both and read the documentaton, but I have no clue how to make it work.
What I have achieved to far is to set up my model, views, serializes and urls to have the original queryset rendered via the Django Rest Framework.
If anyone could give me a hint on how to integrate pandas in this workflow, it would be highly appreciated.
my models.py file
from django.db import models
class Fund(models.Model):
name = models.CharField(max_length=100)
commitment_size = models.IntegerField(blank=True, null=True)
commitment_date = models.DateField(blank=True, null=True)
def __str__(self):
return self.name
my views.py file
from rest_framework import generics
from rest_framework.views import APIView
from pages.models import Fund
from .serializers import FundSerializer
class FundAPIView(generics.ListAPIView):
queryset = Fund.objects.all()
serializer_class = FundSerializer
my serializers.oy file
from rest_framework import serializers
from pages.models import Fund
class FundSerializer(serializers.ModelSerializer):
class Meta:
model = Fund
fields = ('name', 'commitment_size', 'commitment_date')
So i figured it out. First, you need to install django-pandas and django rest framework (but no need to install django REST pandas)
models.py and serializers.py files stay the same as above, but the views file is different
from rest_framework.views import APIView
from rest_framework.response import Response
from django_pandas.io import read_frame # Import django_pandas.io read frame
from pages.models import Fund
from .serializers import FundSerializer
class TestData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
data = Fund.objects.all() # Perform database query
df = read_frame(data) # Transform queryset into pandas dataframe
df['testcolumn'] = "testdata" # Perform some Pandas Operation with dataframe
return Response(df) # Return the result in JSON via Django REST Framework
I am trying to understand Django RESTFramework. I am already familiar with Django. I want to create an endpoint that accepts some text data and processes it and returns it to the user along with the results of the processing (in text). I have completed a couple of tutorials on the topic but I still don't understand how it works. Here is an example from a working tutorial project. How can I edit it to achieve my goal? It all looks automagical.
# views.py
from rest_framework import generics
from .models import Snippet
from .serializers import SnippetSerializer
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
# Here I would like to accept form data and process it before returning it along with the
# results of the processing.
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
Okay, I think you are a newbie in Django rest and try to understand its flow so I can explain it with an example of a subscription plan.
First, create a model in models.py file
from django.db import models
class SubscriptionPlan(models.Model):
plan_name = models.CharField(max_length=255)
monthly_price = models.IntegerField()
yearly_price = models.IntegerField()
Then create views in a view.py file like
from rest_framework.views import APIView
class SubscriptionCreateAPIView(APIView):
serializer_class = SubscriptionSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(
{'message': 'Subscription plan created successfully.',
'data': serializer.data},
status=status.HTTP_201_CREATED
)
and then define a serializer for validation and fields in which we can verify which fields will be included in the request and response object.
serializers.py
from rest_framework import serializers
from .models import SubscriptionPlan
class SubscriptionSerializer(serializers.ModelSerializer):
plan_name = serializers.CharField(max_length=255)
monthly_price = serializers.IntegerField(required=True)
yearly_price = serializers.IntegerField(required=True)
class Meta:
model = SubscriptionPlan
fields = (
'plan_name', 'monthly_price', 'yearly_price',
)
def create(self, validated_data):
return SubscriptionPlan.objects.create(**validated_data)
Now add urls in src/subsciption_module/urls.py
from django.urls import path
from .views import SubscriptionCreateAPIView
app_name = 'subscription_plan'
urlpatterns = [
path('subscription_plan/', SubscriptionCreateAPIView.as_view()),
]
At the end include module url in root urls.py file where your main urls will be located. It will be the same directory which contains settings.py and wsgi.py files.
src/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('src.subscription_plan.urls', namespace='subscription_plan')),
]
That's it. This is how flow works in django rest and you can process data and display data in this way. For more details you can refer django rest docs.
But this is not in any way different from what you do with plain Django. Your SnippetDetail view is just a class-based view, and like any class-based view if you want to do anything specific you override the relevant method. In your case, you probably want to override update() to do your custom logic when receiving a PUT request to update data.
I have a model that I want to use for predictions which I have loaded using pickle and I have a form created in using django. But when a user submits the form I want it to be in store it in a csv format in a variable so I can perform Xgboost prediction on every form the user fills and after it outputs the prediction. COuld it be its not getting any input. New to this
from django.db import models
from django import forms
from django.core.validators import MaxValueValidator, MinValueValidator
# Create your models here.
type_loan=(("Cash loan","Cash loan"),
("Revolving loan","Revolving Loan"))
Gender=(("Male","Male"),
("Female","Female"))
Yes_NO=(("YES","YES"),("NO","NO"))
status=(("Single","Single"),
("Married","Married"),
("Widow","Widow"),
("Seprated","Divorce"))
Highest_Education=(("Secondary","Secondary"),
("Incomplete Higher","Incomplete Higher"),
("Lower Secondary","Lower Secondary"),
("Academic Degree","Academic Degree"))
Income_type=(("Working","Working Class"),
("State Servant","Civil Servant"),
("Commercial Associate","Commercial Associate"),
("Pensioner","Pensioner"),
("Student","Student"),
("Businessman","Business Owner"))
class Applicant(models.Model):
name=models.CharField(default="Jon Samuel",max_length=50,null="True")
Birth_date=models.DateField(default="2018-03-12",blank=False, null=True)
Status=models.CharField(choices=status,max_length=50)
Children=models.IntegerField(default=0,validators=[MinValueValidator(0),MaxValueValidator(17)])
Highest_Education=models.CharField(choices=Highest_Education,max_length=50)
Gender=models.CharField(choices=Gender, max_length=50)
loan_type=models.CharField(choices=type_loan, max_length=50)
own_a_car=models.CharField(choices=Yes_NO,max_length=50)
own_a_house=models.CharField(choices=Yes_NO,max_length=50)
def __str__(self):
return self.name
views.py
from django.shortcuts import render
from .models import Applicant
from .forms import Applicant_form
from django.views.generic import ListView, CreateView, UpdateView
from django.core.cache import cache
import xgboost as xgb
import pickle
from sklearn.preprocessing import LabelEncoder
class CreateMyModelView(CreateView):
model = Applicant
form_class = Applicant_form
template_name = 'loan/index.html'
success_url = '/loan/results'
context_object_name = 'name'
class MyModelListView(ListView):
template_name = 'loan/result.html'
context_object_name = 'Results'
def get_queryset(self):
queryset=Applicant.objects.all()
with open('model/newloan_model','rb') as f:
clf=pickle.load(f)
le=LabelEncoder()
le.fit(queryset)
queryset=le.transform(queryset)
d_test = xgb.DMatrix(queryset)
predict=clf.predict(d_test)
return (predict)
One way to accomplish this is to use a Django package called django-import-export. This way you can export every object inside a model to a csv file.
https://django-import-export.readthedocs.io/en/latest/
I'm trying to customise my Django admin page. I want a single model field to render all the choices passed to it as a CheckboxSelectMultiple, but can't get it to work.
Here is the relevant part of my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
class Event(models.Model):
GROUP_OWNER_CHOICES = (
('vcoe', "VCOE"),
('cssi', 'CSSI'),
('essc', "ESSC"),
('tmscc', "TMSCC"),
('inmc', "INMC"),
('ccs7', "CCS7"),
('ias', "IAS"),
)
group_owner = models.BooleanField(choices=GROUP_OWNER_CHOICES, blank=True, default=False)
I can't use the Django formfield_overrides(https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form) because I have more than 1 BooleanField and would like to keep the other BooleanField's intact.
Here is what I found from other questions
from django.contrib import admin
from .models import Event
from django import forms
class EventGroupOwnerAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(EventGroupOwnerAdminForm, self).__init__(*args,**kwargs)
self.fields["group_owner"].widget = forms.widgets.CheckboxSelectMultiple()
class EventAdmin(admin.ModelAdmin):
form = EventGroupOwnerAdminForm
admin.site.register(Event , EventAdmin)
But the field simply doesnt render anything. Any help?
If I want to register my models with the admin I have to do this like this:
#admin.py
admin.site.register(models.About)
But with multiple models you can't do something like this:
models = (models.Project, models.Client, models.About)
for m in models:
admin.site.register(m)
First of all: why not!? Secondly: imagine one has a lot of models which all should be accessible from the admin interface. How do you do that in a generic way?
admin.site.register has this definition in the library:
def register(self, model_or_iterable, admin_class=None, **options):
so models to be registered can be a single model or iterable object so just use this:
myModels = [models.Project, models.Client, models.About] # iterable list
admin.site.register(myModels)
I tested this in my site and works perfectly fine.
# File: admin.py
from django.contrib import admin
from .models import Project, Client, About
admin.register(Project, Client, About)(admin.ModelAdmin)
With respect to the recent release of Django 1.7, you can use the django.contrib.admin.register decorator to register multiple models that using the same admin class.
from django.contrib import admin
from .models import Project, Client, About
#admin.register(Project, Client, About)
class DefaultAdmin(admin.ModelAdmin):
pass
Update
Consider making a simple call instead of declaring a dummy class
Based on the snippet here, what I usually do is have the following code in my admin.py
from django.db.models import get_models, get_app
from django.contrib import admin
from django.contrib.admin.sites import AlreadyRegistered
def autoregister(*app_list):
for app_name in app_list:
app_models = get_app(app_name)
for model in get_models(app_models):
try:
admin.site.register(model)
except AlreadyRegistered:
pass
autoregister('myapp')
With Django 3.1.3
in admin.py
from .models import Course, Category
admin.site.register(Course)
admin.site.register(Category)
This is better way to regestering multiple models
from django.contrib import admin
from myapp.models import Course, Category
admin.site.register(Course)
admin.site.register(Category)
from django.contrib import admin
from .models import *
#admin.register(Project, Client, About)
class AppAdmin(admin.ModelAdmin):
pass
Here is a wrokaround that attempts to register a custom models to the admin UI if existing else the default one, for that to work, you must follow the convention of naming your custom admin classes as "MyModelAdmin" by appending "Admin" to the end.
for model_name, model in apps.get_app_config('myapp').models.items() :
if '_' not in model_name :
if globals().get(model.__name__+'Admin') :
admin.site.register(model, globals().get(model.__name__+'Admin'))
else :
admin.site.register(model)
-> if you have just one model:
from django.contrib import admin
from .models import MyModel1
class myModel1Admin(admin.ModelAdmin):
list_display = ("name", "address")
admin.site.register(MyModel1, myModel1Admin)
-> but if you have more than one model or ModelAdmin, you can register them separately:
e.g:
from django.contrib import admin
from .models import MyModel1, MyModel2
class myModel1Admin(admin.ModelAdmin):
list_display = ("name", "address")
class myModel2Admin(admin.ModelAdmin):
list_display = ("name", "photo")
admin.site.register(MyModel1, myModel1Admin)
admin.site.register(MyModel2, myModel2Admin)