Добавление маркеров в Openstreetmap Django/Python
У меня проблемы с leaflet и OpenStreetMap, я не могу добавить маркер для каждого доступного задания. это просто отображается как пустая карта. Отладка показывает, что информация отправляется правильно, но карта не обновляется. Вот отладочная информация. Listview работает отлично. и на карте отображается правильный маркер при нажатии на задание в режиме просмотра списка.
(0.001) SELECT "users_job"."id", "users_job"."title", "users_job"."description", "users_job"."city", "users_job"."state", "users_job"."zip", "users_job"."latitude", "users_job"."longitude" FROM "users_job"; args=(); alias=default
Jobs List: [{'id': 1, 'title': 'test job', 'description': 'this is a test', 'city': '*redacted*', 'state': '*redacted*', 'zip': '*redacted*', 'latitude': *redacted*, 'longitude': *redacted*}, {'id': 2, 'title': 'testjob2', 'description': 'This is a test', 'city': '*redacted*', 'state': '*redacted*', 'zip': '*redacted*', 'latitude': *redacted*, 'longitude': *redacted*}, {'id': 3, 'title': 'test job json', 'description': 'json test', 'city': '*redacted*', 'state': '*redacted*', 'zip': '*redacted*', 'latitude': *redacted*, 'longitude': *redacted*}, {'id': 4, 'title': 'jsontest2', 'description': 'asdofmasodfm', 'city': '*redacted*', 'state': '*redacted*', 'zip': '*redacted*', 'latitude': *redacted*, 'longitude': *redacted*}]
(0.002) SELECT "django_session"."session_key", "django_session"."session_data", "django_session"."expire_date" FROM "django_session" WHERE ("django_session"."expire_date" > '2025-03-11T01:18:30.939183+00:00'::timestamptz AND "django_session"."session_key" = '*redacted*') LIMIT 21; args=(datetime.datetime(2025, 3, 11, 1, 18, 30, 939183, tzinfo=datetime.timezone.utc), '*redacted*'); alias=default
(0.002) SELECT "users_user"."id", "users_user"."password", "users_user"."last_login", "users_user"."is_superuser", "users_user"."username", "users_user"."is_staff", "users_user"."is_active", "users_user"."date_joined", "users_user"."email", "users_user"."phone_number", "users_user"."address", "users_user"."city", "users_user"."state", "users_user"."zip", "users_user"."latitude", "users_user"."longitude", "users_user"."avatar", "users_user"."user_type", "users_user"."first_name", "users_user"."last_name" FROM "users_user" WHERE "users_user"."id" = 2 LIMIT 21; args=(2,); alias=default
"GET / HTTP/1.1" 200 8512
Вот форма задания
# Job Form
class JobForm(forms.ModelForm):
title = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
description = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))
address = forms.CharField(max_length=300, widget=forms.TextInput(attrs={'class': 'form-control'}))
city = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
state = forms.CharField(max_length=25, widget=forms.Select(choices=STATE_CHOICES, attrs={'class': 'form-control state-select'})) # Add custom class
zip = forms.CharField(max_length=12, widget=forms.TextInput(attrs={'class': 'form-control'}))
budget = forms.DecimalField(widget=forms.NumberInput(attrs={'class': 'form-control'}))
deadline = forms.DateField(widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}))
document = forms.FileField(widget=forms.ClearableFileInput(attrs={'class': 'form-control'}), required=False)
image = forms.ImageField(widget=forms.ClearableFileInput(attrs={'class': 'form-control'}), required=False)
class Meta:
model = Job
fields = ['title', 'description', 'address', 'city', 'state', 'zip', 'budget', 'deadline', 'document', 'image']
def save(self, commit=True):
job = super().save(commit=False)
if job.zip:
job.latitude, job.longitude = job.get_lat_lng_from_zip(job.zip)
if commit:
job.save()
return job
Вот модель задания
# Job Model
class Job(models.Model):
id = models.BigAutoField(primary_key=True)
customer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
description = models.TextField(max_length=1000, default='No description provided')
address = models.CharField(max_length=255, blank=True, null=True)
city = models.CharField(max_length=100, blank=True, null=True)
state = models.CharField(max_length=25, blank=True, null=True) # Add the state field
zip = models.CharField(max_length=10, default='11111')
latitude = models.FloatField(default=0)
longitude = models.FloatField(default=0)
budget = models.DecimalField(max_digits=12, decimal_places=2)
deadline = models.DateField(default='2021-12-31')
created_at = models.DateTimeField(auto_now_add=True)
document = models.FileField(upload_to='job_documents/', blank=True, null=True)
image = models.ImageField(upload_to='job_images/', blank=True, null=True)
def save(self, *args, **kwargs):
if self.zip:
lat, lng = self.get_lat_lng_from_zip(self.zip)
if lat is not None and lng is not None:
self.latitude = lat
self.longitude = lng
else:
logger.error(f"Failed to get latitude and longitude for zip code: {self.zip}")
if self.city and not self.state:
self.state, lat, lng = self.get_state_and_coords_from_city(self.city, self.zip)
if lat is not None and lng is not None:
self.latitude = lat
self.longitude = lng
super().save(*args, **kwargs)
def get_lat_lng_from_zip(self, zip_code):
url = f'https://nominatim.openstreetmap.org/search?postalcode={zip_code}&format=json&countrycodes=us'
headers = {
'User-Agent': 'ConstructionConnect/1.0 (jonnytombstone@gmail.com)' # Replace with your app name and email
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status() # Raise an HTTPError for bad responses
data = response.json()
logger.debug(f"Response data for zip code {zip_code}: {data}") # Log the response data
if data:
location = data[0]
lat = float(location.get('lat', 0))
lon = float(location.get('lon', 0))
logger.debug(f"Extracted lat: {lat}, lon: {lon} for zip code {zip_code}")
return lat, lon
except requests.RequestException as e:
logger.error(f"Error fetching latitude and longitude for zip code {zip_code}: {e}")
return None, None
Вот вид задания
def home(request):
jobs = Job.objects.all()
jobs_list = list(jobs.values('id', 'title', 'description', 'city', 'state', 'zip', 'latitude', 'longitude'))
# Log the jobs_list data for debugging
logger.debug('Jobs List: %s', jobs_list)
# Job Views
@login_required
def job_detail(request, job_id):
job = get_object_or_404(Job, id=job_id)
comments = job.comments.all()
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
comment = comment_form.save(commit=False)
comment.job = job
comment.author = request.user
comment.save()
return redirect('job_detail', job_id=job.id)
else:
comment_form = CommentForm()
context = {
'job': job,
'comments': comments,
'comment_form': comment_form,
}
return render(request, 'users/job_detail.html', context)