Create "static" HTML Pages For Each Product - html

I have 10k+ products that need their HTML Page and the stuff within is to be static (thus searchable). I am trying to find a way to do the following using django:
Loop over all the items.
Get the matching information.
Fill a model template.
Save such template with the information now static.
As much as I tried looking here on Stack Overflow and in the web, I did not find any instructions to do so.

Build a standard template that has variables for the products. Then on the backend you can search for the products you want and populate the template with their information. Something like this for a concept:
search.html
<form action="{% url 'your_url' %}" method="POST">
{% csrf_token %}
<input type=text name=input value="" />
<input type="submit" value="Submit">
product.html
<html>
<div>Hello {{name}}!</div>
</html>
models.py
class Names:
user_name = models.CharField(max_length=200)
def __str__(self):
return self.user_name
views.py
input = request.POST['input']
name = Names.objects.get(user_name=input)
return render_to_response('product.html', {'name': name})
This will allow your user to search something, pull up the record searched, and place it in the template.
You can use that system for any number of variables.

Related

Creating a Blogpost Like/Dislike Button within Django/Wagtail

I'm new to Django and Wagtail and have looked for a way to implement a "simple" like/dislike button on a blog entry page using Wagtail.
I included a total_likes IntegerField in my model for the page and would like to increment or reduce this int within the database when the user clicks a button on the html template.
The user is not supposed to be logged in. Most tutorials I've found deal with this only for registred users which is not something I want.
I would be glad if somebody could point me in the right direction. The models.py code is below.
I do not understand how to call a function from within a template.
class BlogEntry(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250, blank=False)
body = RichTextField(blank=True)
tags = ClusterTaggableManager(through=BlogEntryTag, blank=True)
categories = ParentalManyToManyField('blog.BlogCategory', blank=False)
total_likes = models.IntegerField(blank=False, default=0)
image = models.ForeignKey(
"wagtailimages.Image",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="+"
)
streamBody = StreamField([
("text", blocks.StaticContentBlock()),
("quotes", blocks.QuoteBlock()),
("image_and_text", blocks.ImageTextBlock()),
("related_articles", blocks.RelatedArticlesBlock()),
], null=True, blank=True)
sidebarBody = StreamField([
("text", blocks.StaticContentBlock()),
("quotes", blocks.QuoteBlock()),
("image_and_text", blocks.ImageTextBlock()),
("related_articles", blocks.RelatedArticlesBlock()),
], null=True, blank=True)
search_fields = Page.search_fields + [
index.SearchField('intro'),
index.SearchField('body'),
]
content_panels = Page.content_panels + [
MultiFieldPanel([
ImageChooserPanel("image"),
FieldPanel('date'),
FieldPanel('tags'),
FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
], heading="Blog information"),
FieldPanel('intro'),
StreamFieldPanel("streamBody"),
]
sidebar_panels = [
MultiFieldPanel([
FieldPanel("sidebarBody"),
], heading="Sidebar Content")
]
edit_handler = TabbedInterface(
[
ObjectList(content_panels, heading="Custom"),
ObjectList(Page.promote_panels, heading="Promote"),
ObjectList(Page.settings_panels, heading="Settings"),
ObjectList(sidebar_panels, heading="Sidebar"),
]
)
def __str__(self):
return self.total_likes
def likePost(self):
self.total_likes += 1
def dislikePost(self):
self.total_likes -= 1
Overview
Welcome to Django and Wagtail, there is a lot to learn but hopefully you are finding it fun. The first thing to wrap your head around is how a website (browser / client) can talk to the server (Python code running Django/Wagtail). Even though your Page model has a likePost method, you will need to provide a way for your Page to handle this kind of request.
The web uses a system of HTTP requests, the most common being GET and POST, where GET is used to pull down data to show to the user, POST is used for when the website wants to send something back to the server.
Django's docs on working with forms may be a good place to start to understand this process a bit more. Once your website has a form (in the HTML template), you can provide a way to 'listen' to this form when submitted. Wagtail has a method that exists on all Page models that is called serve and it allows you to override the normal behaviour.
Solution
In the solution below you will need to do the following:
1. Add two forms to your template (e.g. blog_page.html)
Remember to load the tags wagtailcore_tags so that you can access the page's URL in the form.
For simplicity, two forms have been created, one with a button for like and another with a button for dislike.
Both forms will use the method="POST" and the action (this is the URL to POST to) being the current URL.
Each form contains a csrf_token, you can read more about this in the Django docs but this helps avoid some security issues.
Each form contains a html input that is hidden with a name and value, we will use the name only in the server code to determine what button has been clicked.
{% extends "base.html" %}
{% load wagtailcore_tags %}
... BLOG CONTENT
<form action="{% pageurl page %}" method="POST" role="form">
{% csrf_token %}
<input type="hidden" name="like" value="true">
<input type="submit" value="LIKE">
</form>
<form action="{% pageurl page %}" method="POST" role="form">
{% csrf_token %}
<input type="hidden" name="dislike" value="true">
<input type="submit" value="DISLIKE">
</form>
2. Override the serve method in your Page model
The serve method on the Page model takes the argument request, which is the Django request object and should return a response. Thankfully we do not have to think about how this response is built, just know that we must call the super (original) version of this after any logic.
Check if the current request is a POST request and if so, then check what kind of value has been submitted, depending on the value call the Page method that matches
Update the likePost and dislikePost methods to ensure that the model data gets Saved via self.save()
class BlogEntry(Page):
# ...
def likePost(self):
self.total_likes += 1
self.save() ## note: you may need to ensure you call save to update data
def dislikePost(self):
self.total_likes -= 1
self.save() ## note: you may need to ensure you call save to update data
def serve(self, request):
if request.method == 'POST':
if request.POST.get('like'):
self.likePost()
# a form POST has been submitted with a value for 'like'
if request.POST.get('dislike'):
# a form POST has been submitted with a value for 'dislike'
self.dislikePost()
# ensure we call the super's serve method so that the page loads correctly
return super(BlogPage, self).serve(request)
Good to know
As you have noted, this is a basic request that does not require authentication (sign in) to submit a like, however it is very possible you will get a lot of spam this way and you may want to consider other approaches (even third party systems) to work around this.
This way of storing likes (as an integer) will also not give you much data, just a number at the current point in time, it might be worth tracking individual submissions and then providing a tally to the UI.
Here is a great overview of HTTP from MDN that I have found to be a good reference for understanding how a server handles requests & responses.

Django Wagtail ajax contact form

I have a contact form that appears at the bottom of every page in the footer. I simply included it in my base.html at the bottom. Now i want to figure out a way to submit it. All the examples wagtail provides is under the assumption i have an entire page dedicated to it and hence submits to itself.
This cannot work for me as its not a page.
I have written pseudo code of what I think it should look like .
def submitContact(request):
source_email = request.POST.get('email')
name = request.POST.get('name')
message = request.POST.get('message')
if (source_email is not None) and (name is not None) and (message is not None):
body = "sample"
send_mail(
name,
message,
source_email,
['test#foobar'],
fail_silently=False,
)
Then my form would be something like this
<form class="form-group" role="form" method="post" action="/submitContact">
......
</form>
Ideally if someone could point to Wagtail resources that show how to create endpoints in models that do not inherit from the Page model and are not snippets that maintain "request" content that would be useful. Ideally what I would prefer is to log this data into contact "table" then send the email after.
What should I add to my urls.py to reroute the request with the correct context for the function to retrieve the required variables and thus send the email
Additional info
I wrapped a snippet around the footer to provide some context to it using templatetags, just putting this out there incase it adds value
See below.
#register.inclusion_tag('home/menus/footer.html', takes_context=True)
def footers(context):
return {
'footers': Footers.objects.first(),
'request': context['request'],
}
You should use {% url %} template tag.
urls.py :
from django.conf.urls import url
from yourapp.views import submitContact
urlpatterns = [
url(r'^contact/$', submitContact, name='contact'),
]
Template :
<form class="form-group" role="form" method="post" action="{% url 'contact' %}">
......
</form>
Another improvement is to use Django Form.
Note : prefer lower_case_with_underscores naming style for functions. Use CamelCase for classes. See PEP8 for more information.
Instead of trying to build it yourself, why not take a look at the already existing Form Builder of Wagtail?
It enables you to create a FormPage on which you can display a custom form and even E-mail the results.
Check out the documentation here.

How to delete data from database inline using Symfony

I'm new with Symfony and I'm trying to delete some data from the database using an html table, something that looks like this but I don't know where to start:
Any help is appreciated :)
There are basically 3 choices, whether using symphony or not:
A link to a page (look at Symfony "routes") including the information which entry to delete.
A nice trick is to use the same page and add a query parameter.
This would look something like this in twig:
{% for row in table %}
delete
{% endfor %}
And in symfony:
if($request->get->has('delete'))
{
//delete it from the database
}
//the code that displays your table
This is the easiest way but has a few disadvantages. It is slow as the whole page has to be loaded again. The browsers back-button might not behave as the user might expect.
A html form doing basically the same as 1. but with post
{% for row in table %}
<form action="" method="POST">
<input type="hidden" name="delete" value="{{row.id}}">
<input type="submit" value="delete">
</form>
{% endfor %}
And in symfony use $request->request
Ajax triggered by an onclick event
A javascript deleterow function would send the id via ajax to a special symphony route that returns an JSONResponse and when successful delete the DOM Element with the row.
This is much more complicated and would need a lot more research on your part, but it is the modern way.

How to integrate HTML form into django view and model?

I have one html file which contain submission form.
I want to use this HTML form in django with model and view.
I dont want to use form class in html like
<form method="post" action="">
{% csrf_token %}
{{ form }}
<input type="submit" value="Register"/>
</form>
I want to use complete form code in HTML and use django model to store that data in database.
How can I do that?
Please update the question that you want to use jQuery.Django by defaults generate id for its form element.
As avinash already said you can always inspect the element and get the id and classses but some time we need custom class in that case you can use something like.
If you want to write your own custom fields.
class myForm(forms.ModelForm):
class Meta:
model = ModeName
widgets = {
'field_one': forms.TextInput(attrs={'id':'foo', 'name':'foo'})
'field_two': forms.TextInput(attrs={'id':'bar', 'name':'bar'})
}

Preferred way to POST with params from a listing template in Django

I was looking for some input on the preferred way of making a post request from a list template in Django. The way I'm currently using doesn't quite seem right to me, even though it works.
Let's say I have a table of data from my model, SomeModel, which I'm outputting in a Django GCBV ListView.
class SomeModelList(ListView):
model = SomeModel
In my template I'm iterating over the list of models and outputting each row in a table with some of the data, and I want two buttons which make a POST to perform some operation on the current row's object.
I can write an entire form for each operation manually. Something like:
{% for object in object_list %}
{{ object.name }}</br>
<form method="POST" action="{{ url 'do_something' {{ object.pk }}"><input type="button" value="Do Something"/></form></br>
<form method="POST" action="{{ url 'do_something_else' {{ object.pk }}"><input type="button" value="Do Something Else"/></form></br>
{% endfor %}
It doesn't seem correct to be writing out these form tags like this.
Is this really the best way? Maybe I should have a single giant form around the whole list and use some properties of the button? Maybe I should be doing something with Django forms? Maybe something else entirely?
Thanks!