How can I use the nifty JavaScript date and time widgets that the default admin uses with my custom view?
I have looked through the Django forms documentation, and it briefly mentions django.contrib.admin.widgets, but I don't know how to use it?
Here is my template that I want it applied on.
<form action="." method="POST">
<table>
{% for f in form %}
<tr> <td> {{ f.name }}</td> <td>{{ f }}</td> </tr>
{% endfor %}
</table>
<input type="submit" name="submit" value="Add Product">
</form>
Also, I think it should be noted that I haven't really written a view up myself for this form, I am using a generic view. Here is the entry from the url.py:
(r'^admin/products/add/$', create_object, {'model': Product, 'post_save_redirect': ''}),
And I am relevantly new to the whole Django/MVC/MTV thing, so please go easy...
The growing complexity of this answer over time, and the many hacks required, probably ought to caution you against doing this at all. It's relying on undocumented internal implementation details of the admin, is likely to break again in future versions of Django, and is no easier to implement than just finding another JS calendar widget and using that.
That said, here's what you have to do if you're determined to make this work:
Define your own ModelForm subclass for your model (best to put it in forms.py in your app), and tell it to use the AdminDateWidget / AdminTimeWidget / AdminSplitDateTime (replace 'mydate' etc with the proper field names from your model):
from django import forms
from my_app.models import Product
from django.contrib.admin import widgets
class ProductForm(forms.ModelForm):
class Meta:
model = Product
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.fields['mydate'].widget = widgets.AdminDateWidget()
self.fields['mytime'].widget = widgets.AdminTimeWidget()
self.fields['mydatetime'].widget = widgets.AdminSplitDateTime()
Change your URLconf to pass 'form_class': ProductForm instead of 'model': Product to the generic create_object view (that'll mean from my_app.forms import ProductForm instead of from my_app.models import Product, of course).
In the head of your template, include {{ form.media }} to output the links to the Javascript files.
And the hacky part: the admin date/time widgets presume that the i18n JS stuff has been loaded, and also require core.js, but don't provide either one automatically. So in your template above {{ form.media }} you'll need:
<script type="text/javascript" src="/my_admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
You may also wish to use the following admin CSS (thanks Alex for mentioning this):
<link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>
This implies that Django's admin media (ADMIN_MEDIA_PREFIX) is at /media/admin/ - you can change that for your setup. Ideally you'd use a context processor to pass this values to your template instead of hardcoding it, but that's beyond the scope of this question.
This also requires that the URL /my_admin/jsi18n/ be manually wired up to the django.views.i18n.javascript_catalog view (or null_javascript_catalog if you aren't using I18N). You have to do this yourself instead of going through the admin application so it's accessible regardless of whether you're logged into the admin (thanks Jeremy for pointing this out). Sample code for your URLconf:
(r'^my_admin/jsi18n', 'django.views.i18n.javascript_catalog'),
Lastly, if you are using Django 1.2 or later, you need some additional code in your template to help the widgets find their media:
{% load adminmedia %} /* At the top of the template. */
/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>
Thanks lupefiasco for this addition.
As the solution is hackish, I think using your own date/time widget with some JavaScript is more feasible.
I find myself referencing this post a lot, and found that the documentation defines a slightly less hacky way to override default widgets.
(No need to override the ModelForm's __init__ method)
However, you still need to wire your JS and CSS appropriately as Carl mentions.
forms.py
from django import forms
from my_app.models import Product
from django.contrib.admin import widgets
class ProductForm(forms.ModelForm):
mydate = forms.DateField(widget=widgets.AdminDateWidget)
mytime = forms.TimeField(widget=widgets.AdminTimeWidget)
mydatetime = forms.SplitDateTimeField(widget=widgets.AdminSplitDateTime)
class Meta:
model = Product
Reference Field Types to find the default form fields.
My head code for 1.4 version(some new and some removed)
{% block extrahead %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/widgets.css"/>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/core.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.init.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/actions.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/calendar.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/DateTimeShortcuts.js"></script>
{% endblock %}
Yep, I ended up overriding the /admin/jsi18n/ url.
Here's what I added in my urls.py. Make sure it's above the /admin/ url
(r'^admin/jsi18n', i18n_javascript),
And here is the i18n_javascript function I created.
from django.contrib import admin
def i18n_javascript(request):
return admin.site.i18n_javascript(request)
Starting in Django 1.2 RC1, if you're using the Django admin date picker widge trick, the following has to be added to your template, or you'll see the calendar icon url being referenced through "/missing-admin-media-prefix/".
{% load adminmedia %} /* At the top of the template. */
/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>
Complementing the answer by Carl Meyer, I would like to comment that you need to put that header in some valid block (inside the header) within your template.
{% block extra_head %}
<link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
<script type="text/javascript" src="/media/admin/js/admin/RelatedObjectLookups.js"></script>
{{ form.media }}
{% endblock %}
For Django >= 2.0
Note: Using admin widgets for date-time fields is not a good idea as admin style-sheets can conflict with your site style-sheets in case you are using bootstrap or any other CSS frameworks. If you are building your site on bootstrap use my bootstrap-datepicker widget django-bootstrap-datepicker-plus.
Step 1: Add javascript-catalog URL to your project's (not app's) urls.py file.
from django.views.i18n import JavaScriptCatalog
urlpatterns = [
path('jsi18n', JavaScriptCatalog.as_view(), name='javascript-catalog'),
]
Step 2: Add required JavaScript/CSS resources to your template.
<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script type="text/javascript" src="{% static '/admin/js/core.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static '/admin/css/widgets.css' %}">
<style>.calendar>table>caption{caption-side:unset}</style><!--caption fix for bootstrap4-->
{{ form.media }} {# Form required JS and CSS #}
Step 3: Use admin widgets for date-time input fields in your forms.py.
from django.contrib.admin import widgets
from .models import Product
class ProductCreateForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name', 'publish_date', 'publish_time', 'publish_datetime']
widgets = {
'publish_date': widgets.AdminDateWidget,
'publish_time': widgets.AdminTimeWidget,
'publish_datetime': widgets.AdminSplitDateTime,
}
The below will also work as a last resort if the above failed
class PaymentsForm(forms.ModelForm):
class Meta:
model = Payments
def __init__(self, *args, **kwargs):
super(PaymentsForm, self).__init__(*args, **kwargs)
self.fields['date'].widget = SelectDateWidget()
Same as
class PaymentsForm(forms.ModelForm):
date = forms.DateField(widget=SelectDateWidget())
class Meta:
model = Payments
put this in your forms.py from django.forms.extras.widgets import SelectDateWidget
Here's another 2020 solution, inspired by #Sandeep's. Using the MinimalSplitDateTimeMultiWidget found in this gist, in our Form as below, we can use modern browser date and time selectors (via eg 'type': 'date'). We don't need any JS.
class EditAssessmentBaseForm(forms.ModelForm):
class Meta:
model = Assessment
fields = '__all__'
begin = DateTimeField(widget=MinimalSplitDateTimeMultiWidget())
Another simple solution for Django 3 (3.2) in 2021 ;) cause andyw's solution doesn't work in Firefox...
{% load static %}
{% block extrahead %}
{{ block.super }}
<script type="text/javascript" src="{% static 'admin/js/cancel.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}">
<script src="{% url 'admin:jsi18n' %}"></script>
<script src="{% static 'admin/js/jquery.init.js' %}"></script>
<script src="{% static 'admin/js/core.js' %}"></script>
{{ form.media }}
{% endblock %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Сохранить">
</form>
and you'll able to use your form.
example:
from django.contrib.admin import widgets
date_time = forms.SplitDateTimeField(widget=widgets.AdminSplitDateTime)
What about just assigning a class to your widget and then binding that class to the JQuery datepicker?
Django forms.py:
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_date_field'].widget.attrs['class'] = 'datepicker'
And some JavaScript for the template:
$(".datepicker").datepicker();
Updated solution and workaround for SplitDateTime with required=False:
forms.py
from django import forms
class SplitDateTimeJSField(forms.SplitDateTimeField):
def __init__(self, *args, **kwargs):
super(SplitDateTimeJSField, self).__init__(*args, **kwargs)
self.widget.widgets[0].attrs = {'class': 'vDateField'}
self.widget.widgets[1].attrs = {'class': 'vTimeField'}
class AnyFormOrModelForm(forms.Form):
date = forms.DateField(widget=forms.TextInput(attrs={'class':'vDateField'}))
time = forms.TimeField(widget=forms.TextInput(attrs={'class':'vTimeField'}))
timestamp = SplitDateTimeJSField(required=False,)
form.html
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/admin_media/js/core.js"></script>
<script type="text/javascript" src="/admin_media/js/calendar.js"></script>
<script type="text/javascript" src="/admin_media/js/admin/DateTimeShortcuts.js"></script>
urls.py
(r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
I use this, it's great, but I have 2 problems with the template:
I see the calendar icons twice for every filed in template.
And for TimeField I have 'Enter a valid date.'
models.py
from django.db import models
name=models.CharField(max_length=100)
create_date=models.DateField(blank=True)
start_time=models.TimeField(blank=False)
end_time=models.TimeField(blank=False)
forms.py
from django import forms
from .models import Guide
from django.contrib.admin import widgets
class GuideForm(forms.ModelForm):
start_time = forms.DateField(widget=widgets.AdminTimeWidget)
end_time = forms.DateField(widget=widgets.AdminTimeWidget)
create_date = forms.DateField(widget=widgets.AdminDateWidget)
class Meta:
model=Guide
fields=['name','categorie','thumb']
In Django 10.
myproject/urls.py:
at the beginning of urlpatterns
from django.views.i18n import JavaScriptCatalog
urlpatterns = [
url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'),
.
.
.]
In my template.html:
{% load staticfiles %}
<script src="{% static "js/jquery-2.2.3.min.js" %}"></script>
<script src="{% static "js/bootstrap.min.js" %}"></script>
{# Loading internazionalization for js #}
{% load i18n admin_modify %}
<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script type="text/javascript" src="{% static "/admin/js/jquery.init.js" %}"></script>
<link rel="stylesheet" type="text/css" href="{% static "/admin/css/base.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "/admin/css/forms.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "/admin/css/login.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "/admin/css/widgets.css" %}">
<script type="text/javascript" src="{% static "/admin/js/core.js" %}"></script>
<script type="text/javascript" src="{% static "/admin/js/SelectFilter2.js" %}"></script>
<script type="text/javascript" src="{% static "/admin/js/admin/RelatedObjectLookups.js" %}"></script>
<script type="text/javascript" src="{% static "/admin/js/actions.js" %}"></script>
<script type="text/javascript" src="{% static "/admin/js/calendar.js" %}"></script>
<script type="text/javascript" src="{% static "/admin/js/admin/DateTimeShortcuts.js" %}"></script>
My Django Setup : 1.11
Bootstrap: 3.3.7
Since none of the answers are completely clear, I am sharing my template code which presents no errors at all.
Top Half of template:
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block head %}
<title>Add Interview</title>
{% endblock %}
{% block content %}
<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
Bottom Half:
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/actions.min.js' %}"></script>
{% endblock %}
June 3, 2020 (All answers didn't worked, you can try this solution I used. Just for TimeField)
Use simple Charfield for time fields (start and end in this example) in forms.
forms.py
we can use Form or ModelForm here.
class TimeSlotForm(forms.ModelForm):
start = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'HH:MM'}))
end = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'HH:MM'}))
class Meta:
model = TimeSlots
fields = ('start', 'end', 'provider')
Convert string input into time object in views.
import datetime
def slots():
if request.method == 'POST':
form = create_form(request.POST)
if form.is_valid():
slot = form.save(commit=False)
start = form.cleaned_data['start']
end = form.cleaned_data['end']
start = datetime.datetime.strptime(start, '%H:%M').time()
end = datetime.datetime.strptime(end, '%H:%M').time()
slot.start = start
slot.end = end
slot.save()
Related
See Problem Here
I want to loop over a directory of static images in Django. The images are being looped over correctly, but something is wrong with my <img src /> syntax. I've tried many variations on {{ flag }} but can't get anything to work. Can anybody advise?
In settings.py I created the following STATIC_ROOT object:
STATIC_ROOT = '/Users/TheUnforecastedStorm/Desktop/Code_projects/Portfolio_Site/portfolio_site/entrance/static'
In views.py I joined this file path to my image directory and placed the list of images in the context dictionary. I then included this dictionary in my response:
import os
from django.conf import settings
from django.shortcuts import render
# Create your views here.
def index(request):
# Create a dictionary
context = {}
# Join images directory to index.html view
flags = os.listdir(os.path.join(settings.STATIC_ROOT, "entrance/images/"))
context['flags'] = flags
# Return response
return render(request, "entrance/index.html", context)
I then looped over these images in my template:
<!DOCTYPE html>
{% load static %}
<html>
<head>
<link rel="stylesheet" href="{% static 'entrance/entrance.css' %}">
<script src="{% static 'entrance/entrance.js' %}" type="text/javascript"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
{% for flag in flags %}
<img src="{{ flag }}" alt="problem" />
{% endfor %}
</body>
</html>
#Mark1 Working off my comments from above, I haven't been able to find anything to confirm it but it seems like the {% static %} template tag can only take one extra argument to make a path, so here is something you can try.
In your view:
def index(request):
# Create a dictionary
context = {}
# Join images directory to index.html view
flags = os.listdir(os.path.join(settings.STATIC_ROOT, "entrance/images/"))
# ADD IN THIS LINE HERE
flags = ['entrance/images/'+fl for fl in flags]
context['flags'] = flags
# Return response
return render(request, "entrance/index.html", context)
The line I added in will add "entrance/images/" to the start of all the file names in the directory you are searching.
Then in your template
{% for flag in flags %}
<img src="{% static flag %}" alt="problem" />
{% endfor %}
Let me know if this works.
I'm trying to practice ajax in django but I got this error 'QuerySet' object has no attribute 'META'. But it's showing the data in the traceback but not in the template because of the error.How to fix this?
models.py
from django.db import models
# Create your models here.
class Profile(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
bio = models.CharField(max_length=100)
def __str__(self):
return self.name
I think it has something to do with the views but I cant figure it out.
views.py
from django.shortcuts import render
from .models import Profile
from django.http import JsonResponse
# Create your views here.
def list(request):
return render(request, 'livedata/list.html')
def getProfiles(request):
profiles = Profile.objects.all()
# print(JsonResponse({"profiles": list(profiles.values())}))
return JsonResponse({"profiles": list(profiles.values())})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.list, name='list'),
path('getProfiles', views.getProfiles, name='getProfiles')
]
index.html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
{% comment %} <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> {% endcomment %}
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="{% static 'js/main.js' %}" defer></script>
<title>Hello, world!</title>
</head>
<body>
{% block contents %}{% endblock contents %}
{% block scripts %}{% endblock scripts %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{% comment %} <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> {% endcomment %}
{% comment %} <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> {% endcomment %}
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>
list.html
{% extends 'livedata/index.html' %}
{% block contents %}
<h1>List of live data</h1>
<ul id="display">
</ul>
{% endblock contents %}
{% block scripts %}
<script>
$(document).ready(function () {
setInterval(function () {
$.ajax({
type: 'GET',
url: "{% url 'getProfiles' %}",
success: function (response) {
// console.log(response);
$("#display").empty();
for (var key in response.profiles) {
var temp = "<li>" + response.profiles[key].name + "</li>";
$("#display").append(temp);
}
},
error: function (response) {
alert("Error occured");
}
});
}, 1000);
});
</script>
{% endblock scripts %}
You should not name a view list, list is a builtin function that you use in other views. By defining a view named list, the list(profiles.values()) will call the view with profile.values() as the request.
Rename list to view_list for example and update the url patterns to direct to view_list instead:
def view_list(request):
return render(request, 'livedata/list.html')
def getProfiles(request):
profiles = Profile.objects.all()
# does not refer to the view ↓ but to the list builtin
return JsonResponse({"profiles": list(profiles.values())})
The urls.py thus looks like:
from django.urls import path
from . import views
urlpatterns = [
path('', views.view_list, name='list'),
path('getProfiles', views.getProfiles, name='getProfiles')
]
I have created a project named Test and an app named testing inside this app. I have a model named ModelTesting in the testing app. This model has only one field named prop, which is a CharField of max_length=20. I can insert the items in database without any issue but cannot display them in the homepage. Take a look at my code.
Here is my models.py
from django.db import models
# My Model
class ModelTesting(models.Model):
prop = models.CharField(max_length = 20)
def __str__(self):
return self.prop
Here is my views.py
from django.shortcuts import render
from .models import ModelTesting
# Loads Homepage
def index(request):
all_testing_models = ModelTesting.objects.all()
params = {'all_models': all_testing_models}
return render(request, "index.html", params)
And here is the bootstrap template in which I want to display the items. Also, I have edited the template myself.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.1/css/bootstrap.min.css" integrity="sha384-VCmXjywReHh4PwowAiWNagnWcLhlEJLA5buUprzK8rxFgeH0kww/aWY76TfkUoSX" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>The Properties are:-</h1>
{% for test_model in all_testing_mdoels %}
<h3>{{test_model.prop}}</h3>
{% endfor %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.1/js/bootstrap.min.js" integrity="sha384-XEerZL0cuoUbHE4nZReLT7nx9gQrQreJekYhJD9WNWhH8nEW+0c5qq7aIo2Wl30J" crossorigin="anonymous"></script>
</body>
</html>
This error has occurred in some other projects as well, so I created this project specifically for this purpose. Please take a look and help me.
Thank You.
You're doing all_models in
params = {'all_models': all_testing_models}
and trying to look for all_testing_models in
{% for test_model in all_testing_mdoels %}
<h3>{{test_model.prop}}</h3>
{% endfor %}
Fix either one to match the other.
You may wish to turn on string_if_invalid to help you catch typos better.
I am trying to implement an autocomplete search by following this tutorial
https://medium.com/#ninajlu/django-ajax-jquery-search-autocomplete-d4b4bf6494dd
And i am failing to implement it, and i think it has something to do with my urls or the way i am putting scripts in my .html file.
My search bar is in my index view
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.8.18/themes/base/jquery-ui.css" type="text/css" media="all" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"> </script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
</head>
<body>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'KPI/style.css' %}">
<script>
$(document).ready(function(){
$("#txtSearch").autocomplete({
source: "/login/index",
minLength: 2,
open: function(){
setTimeout(function () {
$('.ui-autocomplete').css('z-index', 99);
}, 0);
}
});
});
</script>
<form id="search" method="POST" action="{% url 'kpi:search' %}">
{% csrf_token %}
<input type="text" class="form-control" id="txtSearch" name="txtSearch">
<button type="submit" class="btn btn-default btn-submit">Submit</button>
</form>
</body>
</html>
urls.py
app_name = 'kpi'
urlpatterns = [
path('login/', views.LoginView.as_view(), name='login'),
path('login/index/', views.IndexView.as_view()),
]
now in the tutorial it says to put this path url(r'^ajax_calls/search/', autocompleteModel), but it doesn't seem like the path has to be this way, so i changed the path to login/index/ and called the class view IndexView which holds the autocompleteModel like so
views.py
class IndexView(LoginRequiredMixin,TemplateView):
template_name = 'KPI/index.html'
def autocompleteModel(self,request):
if request.is_ajax():
q = request.GET.get('term', '').capitalize()
search_qs = Epic.objects.filter(name__icontains=q)
results = []
print(q)
for r in search_qs:
results.append(r.name)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return JsonResponse(data, mimetype)
Epic is the model i am searching on with the value name.
with the code i have above it doesn't do anything, and i'm hoping someone can see a flaw in it.
I've decided to integrate an existing Angular 2 app into my Django REST project.
create Django app with static folder for my frontend:
urls.py:
from django.conf.urls import url
from frontend import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^$', views.index, name='index'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
views.py:
from django.shortcuts import render
def index(request):
"""
Renders the Angular2 SPA
"""
return render(request, template_name='index.html')
move my Angular 2 app to frontend static folder
add static settings in my settings:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'frontend', 'static'),
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
make changes in index.html:
<html>
<head>
<base href="/">
<title>PhotoHub</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% load staticfiles %}
<link rel="stylesheet" href="{% static "node_modules/bootstrap/dist/css/bootstrap.min.css" %}">
<link href="{% static "bower_components/font-awesome/css/font-awesome.min.css" %}" rel="stylesheet" />
<link href="{% static "bower_components/alertify.js/themes/alertify.core.css" %}" rel="stylesheet" />
<link href="{% static "bower_components/alertify.js/themes/alertify.bootstrap.css" %}" rel="stylesheet" />
<link rel="stylesheet" href="{% static "styles.css" %}">
<script src="{% static "bower_components/jquery/dist/jquery.min.js" %}"></script>
<script src="{% static "node_modules/bootstrap/dist/js/bootstrap.min.js" %}"></script>
<script src="{% static "bower_components/alertify.js/lib/alertify.min.js" %}"></script>
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="{% static "node_modules/core-js/client/shim.min.js" %}"></script>
<script src="{% static "node_modules/zone.js/dist/zone.js" %}"></script>
<script src="{% static "node_modules/reflect-metadata/Reflect.js" %}"></script>
<script src="{% static "node_modules/systemjs/dist/system.src.js" %}"></script>
<!-- 2. Configure SystemJS -->
<script src="{% static "systemjs.config.js" %}"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<photohub></photohub>
</body>
</html>
make changes in systemjs.config.js:
(function (global) {
System.config({
//static
defaultJSExtensions: true,
paths: {
// paths serve as alias
'npm:': 'static/node_modules/'
},
// map tells the System loader where to look for things
map: {
app: 'static/dist',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
}
}
});
})(this);
The TypeScript files are compiled in /dist and templates remained in /app. When I used two different servers the path for templateUrl look like this:
templateUrl: './app/app.component.html'
now I'm trying to declare templateUrl this way, but it doesn't work:
templateUrl: '{{ STATIC_URL }}' + '/app/app.component.html'
How to deal with templates urls now?
Response:
"GET /app/components/login/login.component.html HTTP/1.1" 404 2601
Not Found: /app/app.component.html
JavaScript files loaded well:
"GET /app/components/login/login.component.html HTTP/1.1" 404 2601
Not Found: /app/components/register/register.component.html
This solved problem:
templateUrl: 'static/app/app.component.html'
I am not sure what error you're having but you probably should use the static tag to make a URL to a static asset in your template:
{% load static %}
templateUrl: "{% static '/app/app.component.html' %}"
Doc: https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#std:templatetag-static