How create form Html in Django_rest_framework? - django

My Views is :
class TweetsListApiView(generics.ListCreateAPIView):
queryset = Tweet.objects.all()
serializer_class = TweetListSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'components/form.html'
Serializers:
class TweetListSerializer(serializers.ModelSerializer):
likes = serializers.SerializerMethodField('get_likes')
class Meta:
model = Tweet
fields = ['id','content','likes']
def get_likes(self,request):
return random.randint(0,9999)
form.html
{% load rest_framework %}
<form method='Post'>
{% csrf_token %}
{% render_form serializer %}
<button type="submit" class="btn btn-secondary">Add</button>
</form>
urls.py:
path('tweets/',TweetsListApiView.as_view()),
Is it possible to have from one viewclass class TweetsListApiView
standart Rest Page and HTML page where I creating new Tweet. if no
what the best way to create this html using serializer and Django REST

Related

Django CBV inheritance not working as expected

I use these two classes to get the context data and check permissions respectively:
class RestaurantView(View):
def get_context_data(self):
ctx = {'restaurant': get_object_or_404(Restaurant, slug=self.kwargs['slug'])}
return ctx
class ManageRestaurantMixin(LoginRequiredMixin, UserPassesTestMixin, RestaurantView):
def test_func(self):
ctx = super().get_context_data()
return ctx['restaurant'].owner == self.request.user
Now the first one is working, so when i don't need permission i get the expected behavior, for example with this DetailView:
class Info(RestaurantView, DetailView):
model = Restaurant
context_object_name = 'restaurant'
template_name = 'restaurant/info.html'
But then if inherit from ManageRestaurantMixin the permissions are checked as expected, but the context object is not working and the template displays an empty form:
class EditInfo(ManageRestaurantMixin, UpdateView):
model = Restaurant
context_object_name = 'restaurant'
template_name = 'restaurant/edit_info.html'
fields = ['name', 'address', 'logo']
success_url = '/account/myrestaurants'
I get that the context gets overwritten, but i don't get how.
How can i solve this?
Is there a better way to handle this kind of situations?
Edit:
edit_info.html:
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input class="btn btn-primary" type="submit" value="update">
</form>
{% endblock %}

Django How to pass variable from a view to a form view

I have two models. One is project and another is todo. The todo model has a foreign key that is the related project's id.
I have a template that displays the individual project and generates a link to a form to add a todo list. How do I pass the project id to the todo form?
I guess I could simply pass the project id in the URL but is that the best way?
My current views.py
class CompanyProjectsDetailView(DetailView):
model = Project
id = Project.objects.only('id')
template_name = 'company_accounts/project_detail.html'
class TodoCreateView(CreateView):
model = ProjectTodo
template_name = 'company_accounts/add_todo.html'
fields = ['title', 'notes', 'status']
Here is my template:
{% extends 'base.html' %}
{% block content %}
<h1>Add Todo</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="save">
</form>
{% endblock content %}
To check to see if the project id is being passed to the form I have tried {{ project.id }} in the template and several other things that have not worked.
Adding this to the views solved the issue:
class TodoCreateView(CreateView):
model = ProjectTodo
template_name = 'company_accounts/add_todo.html'
fields = ['title', 'notes', 'status']
def form_valid(self, form):
project = get_object_or_404(Project, id=self.kwargs.get('pk'))
todo = form.save(commit=False)
todo.project = project
todo.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('project_detail', args=[self.kwargs.get('pk')])

queryset when building django form

I am trying to get specific querysets based when a customer-specific form loads, showing only that customer's name (embedded as an ID field), its respective locations and users.
The idea is to select one user and any number of locations from a multichoice box.
I've tried to pass the ID as a kwarg but am getting a KeyError. I've tried the kwarg.pop('id') as found on the web and same issue. Any advice?
forms.py
class LocGroupForm(forms.ModelForm):
class Meta:
model = LocationsGroup
fields = ('group_name', 'slug', 'customer', 'location', 'user_id',)
def __init__(self, *args, **kwargs):
qs = kwargs.pop('id')
super(LocGroupForm, self).__init__(*args, **kwargs)
self.fields['customer'].queryset = Customers.objects.get(pk=qs)
self.fields['location'].queryset = CustomerLocations.objects.filter(customer_id=qs)
self.fields['user_id'].queryset = CustomerUsers.objects.filter(customer_id=qs)
here is my view. it's just a generic view
views.py
class LocGroupCreate(LoginRequiredMixin, CreateView):
form_class = LocGroupForm
template_name = 'ohnet/a_gen_form.html'
the template is a dry template I use for all my forms- admittedly something I mostly stole from a tutorial
{% extends "ohnet/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% load static %}
<div class="container">
<h1>{{ title }}</h1>
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="submit" value="Submit">
</form>
</div>
{% endblock content %}
This is the KeyError from the form load.
You need to pass a value for the id when constructing the LocGroupForm, you can do that by overriding get_form_kwargs:
class LocGroupCreate(LoginRequiredMixin, CreateView):
form_class = LocGroupForm
template_name = 'ohnet/a_gen_form.html'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['id'] = …
return kwargs
You will need to fill in the … that specifies the value passed as id to the form. This might for example be self.request.user.pk, or a URL parameter with self.kwargs['name-of-url-parameter']

Using my own template beside django rest framework one to upload a file

I did the upload of an image with some information using a form with Django Rest Framework, it works but displayed using DRF default template, I want to use my own template so that i can add more button and link.
When i looked at that, it's about creating my template "api.html" in a folder rest_framework in my folder of templates but i don't know what i can put in the template content that i want to create.
My views :
class ImageViewSet(viewsets.ModelViewSet):
queryset = Video.objects.all()
serializer_class = ImageWatermarkSerializer
filter_backends = (filters.DjangoFilterBackend,filters.OrderingFilter,)
filter_fields = ('completed',)
ordering = ('-date_created',)
For the serializer :
class ImageWatermarkSerializer(serializers.ModelSerializer):
image = serializers.FileField(max_length=None,use_url=True)
class Meta:
model = Image
fields = ('id', 'image_name', 'image_desc', 'date_created', 'image', 'completed', 'size')
My models :
class Video(models.Model):
image_name = models.CharField(max_length=50)
image_desc = models.TextField(max_length=200)
completed = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now=True)
image = models.FileField(upload_to='imgs', default='/home/None/No-image.mp4')
size = models.IntegerField(default=10)
def __str__(self):
return "%s" % self.image_name
In my urls.py:
router = routers.DefaultRouter()
router.register(r'upl', views.ImageViewSet)
urlpatterns = [
url(r'^upload/', include(router.urls)), ]
As you already created your api.html file, you need to define template_name in your api view.
renderer_classes = [TemplateHTMLRenderer]
template_name = 'api.html'
And in your api.html
{% load rest_framework %}
<form class="form-horizontal" action="{% url 'upload' %}" method="post" novalidate enctype="multipart/form-data">
{% csrf_token %}
# this will include your serializer fields
{% render_form serializer %}
# Here you can customize your buttons
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</div>
</form>
If you need to change the image field styles DRF gives you style attribute,
image = serializers.FileField(
style={'template': 'app/image.html'}
)
Find more details at docs

Setting a parents value in a childs object's model form in Django?

I wish for one of a parent's variables to be pre-populated in a child's model form specifically a serial number. I have managed to get the serial number as part of the URL but would like to figure out how it can be implemented as a variable on the form page.
Models.py
class Product(models.Model):
serial_number = models.CharField(unique=True, max_length=15)
class ProductInstance(models.Model):
serial_number = models.ForeignKey('Product', on_delete=models.SET_NULL, null=True)
Views.py
class ProductInstanceCreate(CreateView):
model = ProductInstance
template_name = 'myapp/edit_productinstance.html'
form_class = GunInstanceForm
def get_success_url(self):
return reverse_lazy ('product-detail', kwargs={'pk': self.object.serial_number.pk})
Forms.py
class ProductInstanceForm(forms.ModelForm):
class Meta:
model = ProductInstance
fields = '__all__'
templates/myapp/product_detail.html
...
New
...
urls.py
urlpatterns += [
url(r'^productinstance/(?P<serial_number>[-\w]+)/create/$', views.ProductInstanceCreate.as_view(), name='productinstance_create'),]
templates/myapp/edit_productinstance_form.html
{% extends "base_generic.html" %}
{% block content %}
<h2>Serial Number: {{ serial_number }}</h2>
</br>
<form action="" method="post">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type="submit" value="Submit" />
</form>
</br>
Back
{% endblock %}
So currently I can create a URL such as: productinstance/D1430913/create/
I now need to know:
How to use it as a variable for the title?
How to set the the forms default value to it?
For the title:
<h2>Serial Number: {{ form.serial_number.value }}</h2>
I believe if you modify your CreateView like so and implement the serial_number_func() with whatever you need to get the serial number, this will do what you want:
class ProductInstanceCreate(CreateView):
model = ProductInstance
template_name = 'myapp/edit_productinstance.html'
form_class = GunInstanceForm
def get_form_kwargs(self):
kwargs = super(ProductInstanceCreate, self).get_form_kwargs()
kwargs['serial_number'] = serial_number_func()
return kwargs